Files
HP_InHand_IG502/APPS_UNCOMPILED/lib/mcprotocol/comfx.py
2025-04-30 08:48:49 -05:00

314 lines
11 KiB
Python

# uncompyle6 version 3.9.2
# Python bytecode version base 3.7.0 (3394)
# Decompiled from: Python 3.8.19 (default, Mar 20 2024, 15:27:52)
# [Clang 14.0.6 ]
# Embedded file name: /var/user/app/device_supervisorbak/device_supervisor/lib/mcprotocol/comfx.py
# Compiled at: 2024-04-18 03:12:58
# Size of source mod 2**32: 11460 bytes
"""
mcprotocol
Created on 2021/3/31
@author: Lius
"""
import re
from typing import NoReturn
from .mcformat import SerialModel
DEVICE_READ = 48
DEVICE_WRITE = 49
FORCE_ON = 55
FORCE_OFF = 56
ENQ = 5
STX = 2
ETX = 3
ACK = 6
NAK = 21
class ComFx:
def __init__(self, channel):
self.channel = channel
self._wordsize = 4
def _get_sum_check_code(self, calc_data):
""" Get sum check code.
"""
res = 0
for byte in calc_data:
res += byte
return res
def _encode_value(self, value, mode='short', isSigned=False):
"""encode com protocol value data to byte.
"""
try:
if mode == "byte":
value = value & 255
value.to_bytes(1, "little", signed=isSigned)
value_byte = format(value, "x").rjust(2, "0").upper().encode()
else:
if mode == "short":
value = value & 65535
value.to_bytes(2, "little", signed=isSigned)
value_byte = format(value, "x").rjust(4, "0").upper().encode()
else:
if mode == "long":
value = value & 4294967295L
value.to_bytes(4, "little", signed=isSigned)
value_byte = format(value, "x").rjust(8, "0").upper().encode()
else:
raise ValueError("Please input value type")
except:
raise ValueError("Exceeeded Device value range")
return value_byte
def _decode_value(self, byte, isSigned=False):
"""decode byte to value
"""
try:
value = int(byte.decode(), 16)
if isSigned:
bit = 16
if byte & 1 << bit - 1 != 0:
value = byte - (1 << bit)
except:
raise ValueError("Could not decode byte to value")
return value
def _check_cmdanswer(self, recv_data):
"""check command answer.
"""
if recv_data == b'' or recv_data[0] == ACK:
return "No response data."
if recv_data[0] == NAK:
return "Illegal request data."
def _x_or_y_offset(self, devicenum):
return int(devicenum / 10)
def _s_or_m_offset(self, devicenum):
return int(devicenum / 8)
def _get_read_address(self, devicecode, devicenum):
if devicecode == "Y":
return self._x_or_y_offset(int(devicenum)) + 160
if devicecode == "X":
return self._x_or_y_offset(int(devicenum)) + 128
if devicecode == "M":
return self._s_or_m_offset(int(devicenum)) + 256
if devicecode == "S":
return self._s_or_m_offset(int(devicenum))
if devicecode == "D":
return int(devicenum) * 2 + 4096
if devicecode.startswith("CN"):
return int(devicenum) * 2 + 2560
if devicecode.startswith("TN"):
return int(devicenum) * 2 + 2048
def _device_read(self, headdevice, readsize):
"""read in byte units.
"""
request_data = bytes()
request_data += STX.to_bytes(1, "big")
request_data += DEVICE_READ.to_bytes(1, "big")
devicecode = re.search("\\D+", headdevice).group(0)
devicenum = re.search("\\d.*", headdevice).group(0)
address = "{:x}".format(self._get_read_address(devicecode, devicenum))
request_data += address.rjust(4, "0").upper().encode()
size_value = readsize & 65535
size_value.to_bytes(2, "little", signed=False)
request_data += format(size_value, "x").rjust(2, "0").upper().encode()
request_data += ETX.to_bytes(1, "big")
request_data += self._encode_value(self._get_sum_check_code(request_data[1[:None]]), "byte")
self.channel._send(request_data)
recv_data = self.channel._recv()
check_res = self._check_cmdanswer(recv_data)
if check_res:
return ([], check_res)
return (
recv_data[1[:readsize * 2 + 1]], None)
def batchread_wordunits(self, headdevice, readsize):
"""batch read in word units.
"""
recv_data, error = self._device_read(headdevice, readsize * 2)
if error:
return (
recv_data, error)
word_values = []
_wordsize = 4
data_index = 0
for _ in range(readsize):
wordvalue = self._decode_value(recv_data[data_index[:data_index + _wordsize]])
word_values.append(wordvalue >> 8 | (wordvalue & 255) << 8)
data_index += _wordsize
return (
word_values, None)
def is_octal_device(self, headdevice):
devicecode = re.search("\\D+", headdevice).group(0)
if devicecode in ('X', 'Y'):
return True
return False
def _read_bit_device(self, headdevice, readsize):
"""read in byte units.
"""
request_data = bytes()
request_data += STX.to_bytes(1, "big")
request_data += DEVICE_READ.to_bytes(1, "big")
devicecode = re.search("\\D+", headdevice).group(0)
devicenum = re.search("\\d.*", headdevice).group(0)
address = "{:x}".format(self._get_read_address(devicecode, devicenum))
request_data += address.rjust(4, "0").upper().encode()
size_value = readsize & 65535
size_value.to_bytes(2, "little", signed=False)
request_data += format(size_value, "x").rjust(2, "0").upper().encode()
request_data += ETX.to_bytes(1, "big")
request_data += self._encode_value(self._get_sum_check_code(request_data[1[:None]]), "byte")
self.channel._send(request_data)
recv_data = self.channel._recv()
check_res = self._check_cmdanswer(recv_data)
if check_res:
return ([], check_res)
return (
recv_data[1[:readsize * 2 + 1]], None)
def batchread_bitunits(self, headdevice, readsize):
"""batch read in bit units.
"""
bit = 16
if self.is_octal_device(headdevice):
bit = 8
elif readsize % bit == 0:
read_word_size = int(readsize / bit)
else:
read_word_size = int(readsize / bit) + 1
_recv, error = self._read_bit_device(headdevice, readsize * 2)
if error:
return (
_recv, error)
recv_data = []
_wordsize = 4
data_index = 0
for _ in range(readsize):
wordvalue = self._decode_value(_recv[data_index[:data_index + _wordsize]])
recv_data.append(wordvalue >> 8 | (wordvalue & 255) << 8)
data_index += _wordsize
bit_values = []
data_index = 0
for i in range(read_word_size):
bit_list_of_word = [int(x) for x in str(bin(recv_data[i]))[2[:None]].rjust(bit, "0")]
bit_list_of_word.reverse()
bit_values += bit_list_of_word
data_index += 1
sidx = int(re.search("\\d.*", headdevice).group(0))
bit_values = bit_values[sidx[:sidx + readsize]]
return (bit_values, None)
def _device_write(self, headdevice, values):
"""write in byte units.
"""
request_data = bytes()
request_data += STX.to_bytes(1, "big")
request_data += DEVICE_WRITE.to_bytes(1, "big")
devicecode = re.search("\\D+", headdevice).group(0)
devicenum = re.search("\\d.*", headdevice).group(0)
address = "{:x}".format(self._get_read_address(devicecode, devicenum))
request_data += address.rjust(4, "0").upper().encode()
size_value = len(values)
size_value.to_bytes(2, "little", signed=False)
request_data += format(size_value, "x").rjust(2, "0").upper().encode()
for value in values:
value.to_bytes(1, "little", signed=False)
request_data += format(value, "x").rjust(2, "0").upper().encode()
request_data += ETX.to_bytes(1, "big")
request_data += self._encode_value(self._get_sum_check_code(request_data[1[:None]]), "byte")
self.channel._send(request_data)
recv_data = self.channel._recv()
if recv_data != b'':
check_res = self._check_cmdanswer(recv_data)
if check_res:
return ([], check_res)
return (None, None)
def batchwrite_wordunits(self, headdevice, values):
"""batch write in word units.
"""
wirte_values = list()
for value in values:
value = value & 65535
wirte_values.append(value & 255)
wirte_values.append(value >> 8)
print(wirte_values)
recv_data, error = self._device_write(headdevice, wirte_values)
if error:
if error != "No response data.":
return (
recv_data, error)
return (None, None)
def _get_write_bit_addr(self, headdevice, bit):
devicecode = re.search("\\D+", headdevice).group(0)
devicenum = re.search("\\d.*", headdevice).group(0)
if devicecode == "Y":
return int(devicenum, 8) << 8 | 5
if devicecode == "X":
return int(devicenum, 8) << 8 | 4
if devicecode == "M":
return int(devicenum, 8) << 8 | 8
if devicecode == "S":
return int(devicenum, 8) << 8
def _write_bit_device(self, cmd, addr):
"""write in byte units.
"""
request_data = bytes()
request_data += STX.to_bytes(1, "big")
request_data += cmd.to_bytes(1, "big")
address = "{:x}".format(addr)
request_data += address.rjust(4, "0").upper().encode()
request_data += ETX.to_bytes(1, "big")
request_data += self._encode_value(self._get_sum_check_code(request_data[1[:None]]), "byte")
self.channel._send(request_data)
recv_data = self.channel._recv()
if recv_data != b'':
check_res = self._check_cmdanswer(recv_data)
if check_res:
return ([], check_res)
return (None, None)
def batchwrite_bitunits(self, headdevice, values):
"""batch read in bit units.
"""
for index, value in enumerate(values):
if not value == 0:
if not value == 1:
raise ValueError("Each value must be 0 or 1. 0 is OFF, 1 is ON.")
write_cmd = 55 if value == 1 else 56
addess = self._get_write_bit_addr(headdevice, index)
recv_data, error = self._write_bit_device(write_cmd, addess)
if error:
if error != "No response data.":
return (
recv_data, error)
return (None, None)
def get_plc_status(self):
request_data = bytes()
request_data += ENQ.to_bytes(1, "big")
self.channel._send(request_data)
recv_data = self.channel._recv()
if recv_data != b'':
if recv_data[0] == ACK:
return True
return False