|  | @@ -1,4 +1,6 @@
 | 
	
		
			
				|  |  | -from modbus import Modbus, MBError, NoResponseError
 | 
	
		
			
				|  |  | +from modbus import Modbus
 | 
	
		
			
				|  |  | +from updater import Updater
 | 
	
		
			
				|  |  | +from sys_params import IO_SysParams
 | 
	
		
			
				|  |  |  import colorama
 | 
	
		
			
				|  |  |  from colorama import Fore
 | 
	
		
			
				|  |  |  import time
 | 
	
	
		
			
				|  | @@ -6,90 +8,14 @@ import os
 | 
	
		
			
				|  |  |  import struct
 | 
	
		
			
				|  |  |  import random
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -models = {0x100: 'MDIO_88', 0x200: 'MAO_8', 0x300: 'MAI_12'}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -MODEL_MDIO_88 = 0x0100
 | 
	
		
			
				|  |  | -MODEL_MAO_8 = 0x0200
 | 
	
		
			
				|  |  | -MODEL_MAI_12 = 0x0300
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -SYS_TEST_OK = 0x0001
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -reg_table = {'in_bits': 0x0100, 'in_cnt': 0x0102, 'in_mode': 0x0120, 'in_norm': 0x0122, 'in_deb_start': 0x124,
 | 
	
		
			
				|  |  | -             'out_cur': 0x0200, 'out_mode': 0x0202, 'out_mode_save': 0x0203, 'pwm_duty': 0x0210,
 | 
	
		
			
				|  |  | -             'pwm_duty_save': 0x0220, 'pwm_per': 0x0230, 'pwm_per_save': 0x0240, 
 | 
	
		
			
				|  |  | -             'rtc_unix': 0x0802, 'rtc_sinhro': 0x0804, 'uptime': 0x0800, 'log_info': 0x0900, 
 | 
	
		
			
				|  |  | -             'log_ent': 0x0901, 'arch_cap': 0x0902, 'arch_ent': 0x0903,
 | 
	
		
			
				|  |  | -             'model': 0x0080, 'prod_date': 0x0081, 'serial_number': 0x0083, 'fw_ver': 0x0085, 
 | 
	
		
			
				|  |  | -             'test_status': 0x0089, 'password': 0x008A}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -class IO_Module(Modbus):
 | 
	
		
			
				|  |  | -    def __init__(self, tty: str, brate: int, address: int):
 | 
	
		
			
				|  |  | -        super().__init__(tty, brate, address)
 | 
	
		
			
				|  |  | -        self.update_segment_number = 0
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    def iap_start(self):
 | 
	
		
			
				|  |  | -        """Reboot device in IAP mode"""
 | 
	
		
			
				|  |  | -        request = bytes((self.address, 0x41, 0x01))
 | 
	
		
			
				|  |  | -        response = self.raw_communicate(request + self._crc(request))
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    def write_fw_start(self, size: int):
 | 
	
		
			
				|  |  | -        """Ask device to start update"""
 | 
	
		
			
				|  |  | -        self.update_segment_number = 0
 | 
	
		
			
				|  |  | -        request = bytes((self.address, 0x41, 0x01, 0xEF, 0xBE, 0xAD, 0xDE)) + size.to_bytes(4, 'big')
 | 
	
		
			
				|  |  | -        response = self.raw_communicate(request + self._crc(request), 5)
 | 
	
		
			
				|  |  | -        if len(response) == 0:
 | 
	
		
			
				|  |  | -            raise NoResponseError('No response on WRITE_START command')
 | 
	
		
			
				|  |  | -        if len(response) != 5:
 | 
	
		
			
				|  |  | -            raise MBError('Incorrect response length')
 | 
	
		
			
				|  |  | -        if response[:3] != bytes((self.address, 0x41, 0x01)):
 | 
	
		
			
				|  |  | -            raise MBError('Incorrect response')
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    def write_fw_part(self, data: bytes):
 | 
	
		
			
				|  |  | -        """Write piece of FW data in IAP mode"""
 | 
	
		
			
				|  |  | -        header = bytes((self.address, 0x41, 0x02))
 | 
	
		
			
				|  |  | -        request = b''.join((header, self.update_segment_number.to_bytes(2, 'big'), data))
 | 
	
		
			
				|  |  | -        response = self.raw_communicate(request + self._crc(request), 5)
 | 
	
		
			
				|  |  | -        # self.print_hex(response)
 | 
	
		
			
				|  |  | -        if len(response) != 5:
 | 
	
		
			
				|  |  | -            raise MBError('Incorrect response length')
 | 
	
		
			
				|  |  | -        if (response[:3]) != header:
 | 
	
		
			
				|  |  | -            raise MBError('Incorrect response')
 | 
	
		
			
				|  |  | -        self.update_segment_number += 1
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    def iap_finish(self):
 | 
	
		
			
				|  |  | -        """Complete FW transmission and check response"""
 | 
	
		
			
				|  |  | -        header = request = bytes((self.address, 0x41, 0x03))
 | 
	
		
			
				|  |  | -        response = self.raw_communicate(request + self._crc(request), 5)
 | 
	
		
			
				|  |  | -        if len(response) != 5:
 | 
	
		
			
				|  |  | -            raise MBError('Incorrect response length')
 | 
	
		
			
				|  |  | -        if response[:3] != header:
 | 
	
		
			
				|  |  | -            raise MBError('Incorrect response')
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    def update(self, path):
 | 
	
		
			
				|  |  | -        self.MB_TIMEOUT = 3
 | 
	
		
			
				|  |  | -        size = os.path.getsize('fw.bin')
 | 
	
		
			
				|  |  | -        print('Switch to IAP mode')
 | 
	
		
			
				|  |  | -        self.iap_start()
 | 
	
		
			
				|  |  | -        time.sleep(4)
 | 
	
		
			
				|  |  | -        print(f'Start writing {size} bytes of FW')
 | 
	
		
			
				|  |  | -        self.write_fw_start(size)
 | 
	
		
			
				|  |  | -        time.sleep(2)
 | 
	
		
			
				|  |  | -        print(f'Open FW file "{path}"...')
 | 
	
		
			
				|  |  | -        with open(path, 'rb') as f:
 | 
	
		
			
				|  |  | -            done = progress_cur = progress_pre = 0
 | 
	
		
			
				|  |  | -            while True:
 | 
	
		
			
				|  |  | -                buf = f.read(128)
 | 
	
		
			
				|  |  | -                if len(buf):
 | 
	
		
			
				|  |  | -                    self.write_fw_part(buf)
 | 
	
		
			
				|  |  | -                    progress_cur = done / size
 | 
	
		
			
				|  |  | -                else:
 | 
	
		
			
				|  |  | -                    break
 | 
	
		
			
				|  |  | -        print('End of transmission')
 | 
	
		
			
				|  |  | -        self.iap_finish()
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +class IO_Module:
 | 
	
		
			
				|  |  | +    def __init__(self, modbus: Modbus):
 | 
	
		
			
				|  |  | +        self.modbus = modbus
 | 
	
		
			
				|  |  | +        self.updater = Updater(self.modbus)
 | 
	
		
			
				|  |  | +        self.sys = IO_SysParams(self.modbus)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +'''
 | 
	
		
			
				|  |  |      # 0x0100 - текущее состояние входов
 | 
	
		
			
				|  |  |      def get_inputs_bit(self) -> str:
 | 
	
		
			
				|  |  |          data = self.read_holding_registers(reg_table['in_bits'], 1)
 | 
	
	
		
			
				|  | @@ -227,55 +153,10 @@ class IO_Module(Modbus):
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      def set_rtc(self, utc):
 | 
	
		
			
				|  |  |          self.write_uint32(reg_table['rtc_sinhro'], utc)
 | 
	
		
			
				|  |  | +'''
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -def set_system_vars(dev: IO_Module, password: int):
 | 
	
		
			
				|  |  | -    # Отправка пароля для разблокирования доступа к системным настройкам
 | 
	
		
			
				|  |  | -    dev.write_holding_register(reg_table['password'], password)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    # time.sleep(0.1)
 | 
	
		
			
				|  |  | -    # Модель
 | 
	
		
			
				|  |  | -    # dev.write_holding_register(reg_table['model'], SYS_MODEL_MDIO_88)
 | 
	
		
			
				|  |  | -    # Дата производства
 | 
	
		
			
				|  |  | -    # dev.write_holding_register(reg_table['prod_time'], int(time.time()) - 3600*24)
 | 
	
		
			
				|  |  | -    # Серийный номер
 | 
	
		
			
				|  |  | -    # dev.write_holding_register(reg_table['serial'], random.randint(10000, 1000000))
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    # Статус тестирования
 | 
	
		
			
				|  |  | -    # dev.write_holding_register(reg_table['test_status'], SYS_TEST_OK)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -def get_system_vars(dev: IO_Module):
 | 
	
		
			
				|  |  | -    """Запрос системных настроек и параметров"""
 | 
	
		
			
				|  |  | -    # Модель
 | 
	
		
			
				|  |  | -    model = dev.read_holding_registers(reg_table['model'], 1)[0]
 | 
	
		
			
				|  |  | -    print("Model:       ", models[model])
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    # Дата производства    
 | 
	
		
			
				|  |  | -    prod_date = dev.read_uint32_holding(reg_table['prod_date'])
 | 
	
		
			
				|  |  | -    print("Prod date:   ", prod_date)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    # Серийный номер
 | 
	
		
			
				|  |  | -    serial_number = dev.read_uint32_holding(reg_table['serial_number'])
 | 
	
		
			
				|  |  | -    print("SN:          ", serial_number)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    # Версия ПО
 | 
	
		
			
				|  |  | -    fw_bytes = b''
 | 
	
		
			
				|  |  | -    data = dev.read_holding_registers(reg_table['fw_ver'], 4)
 | 
	
		
			
				|  |  | -    fw_raw = list(data)
 | 
	
		
			
				|  |  | -    fw_raw.reverse()
 | 
	
		
			
				|  |  | -    for i in fw_raw:
 | 
	
		
			
				|  |  | -        fw_bytes += i.to_bytes(2, 'little')
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    fw = fw_bytes.decode('utf-8')
 | 
	
		
			
				|  |  | -    print("FW version:  ", fw)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    # Статус тестирования
 | 
	
		
			
				|  |  | -    test_status = dev.read_holding_registers(reg_table['test_status'], 1)[0]
 | 
	
		
			
				|  |  | -    print("Test status: ", test_status)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    
 | 
	
		
			
				|  |  | +   
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  def main():
 | 
	
	
		
			
				|  | @@ -285,8 +166,6 @@ def main():
 | 
	
		
			
				|  |  |      
 | 
	
		
			
				|  |  |      # dev.update('fw.bin')
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    # Запрос системных параметров, установка времени
 | 
	
		
			
				|  |  | -    
 | 
	
		
			
				|  |  |      # print('Device uptime:', dev.get_uptime())
 | 
	
		
			
				|  |  |      # unix_time = dev.get_rtc()
 | 
	
		
			
				|  |  |      # print(f'RTC: {time.ctime(unix_time)}. Unix time stamp:  {unix_time}')
 | 
	
	
		
			
				|  | @@ -296,9 +175,6 @@ def main():
 | 
	
		
			
				|  |  |      # unix_time = dev.get_rtc()
 | 
	
		
			
				|  |  |      # print(f'RTC: {time.ctime(unix_time)}. Unix time stamp:  {unix_time}')
 | 
	
		
			
				|  |  |      
 | 
	
		
			
				|  |  | -    set_system_vars(dev, 1234)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    # get_system_vars(dev)
 | 
	
		
			
				|  |  |      
 | 
	
		
			
				|  |  |      return
 | 
	
		
			
				|  |  |  
 |