Compare commits
2 Commits
c0097d1ee6
...
20765cdc06
Author | SHA1 | Date | |
---|---|---|---|
20765cdc06 | |||
55f6f4a60d |
97
tic.py
97
tic.py
@ -1,4 +1,5 @@
|
|||||||
import logging
|
import logging
|
||||||
|
import time
|
||||||
|
|
||||||
import tic_device
|
import tic_device
|
||||||
import tic_standard
|
import tic_standard
|
||||||
@ -11,8 +12,9 @@ TIC_ETX = b'\x03'
|
|||||||
TIC_SGR = b'\x0a'
|
TIC_SGR = b'\x0a'
|
||||||
TIC_EGR = b'\x0d'
|
TIC_EGR = b'\x0d'
|
||||||
|
|
||||||
TIC_MODE_STD = 1
|
TIC_MODE_STD = "standard"
|
||||||
TIC_MODE_HIS = 2
|
TIC_MODE_HIS = "historique"
|
||||||
|
|
||||||
|
|
||||||
type_str = {
|
type_str = {
|
||||||
'61': "Compteur monophasé 60 A généralisation Linky G3 - arrivée puissance haute",
|
'61': "Compteur monophasé 60 A généralisation Linky G3 - arrivée puissance haute",
|
||||||
@ -85,48 +87,40 @@ class Tic:
|
|||||||
self.device_serial = None
|
self.device_serial = None
|
||||||
self.mode = None
|
self.mode = None
|
||||||
self._tic = None
|
self._tic = None
|
||||||
|
self._cb_ads = None
|
||||||
|
self._cb_msg = None
|
||||||
|
|
||||||
|
def set_mode(self, mode):
|
||||||
|
if mode == TIC_MODE_STD:
|
||||||
|
self.mode = TIC_MODE_STD
|
||||||
|
self._tic = tic_standard.TicStandard()
|
||||||
|
self.device.set_baudrate(9600)
|
||||||
|
log.info(f"set_mode: {self._tic.name()}")
|
||||||
|
elif mode == TIC_MODE_HIS:
|
||||||
|
self.mode = TIC_MODE_HIS
|
||||||
|
self._tic = tic_hist.TicHist()
|
||||||
|
self.device.set_baudrate(1200)
|
||||||
|
log.info(f"set_mode: {self._tic.name()}")
|
||||||
|
else:
|
||||||
|
self.mode = None
|
||||||
|
self._tic = None
|
||||||
|
log.info(f"set_mode: unsupported")
|
||||||
|
|
||||||
def detect_mode(self):
|
def detect_mode(self):
|
||||||
if self._detect_mode():
|
for mode in ( TIC_MODE_STD, TIC_MODE_HIS ):
|
||||||
return
|
self.set_mode(mode)
|
||||||
if self.device.is_serial():
|
f = self.get_frame()
|
||||||
log.debug("tring speed 1200bps")
|
if not f:
|
||||||
self.device.set_baudrate(1200)
|
continue
|
||||||
if self._detect_mode():
|
groups = self.split_frame(f)
|
||||||
return
|
for group in groups:
|
||||||
log.error("no TIC protocol detected")
|
if not self.check_sum(group):
|
||||||
return None
|
continue
|
||||||
|
self.decode_group(group)
|
||||||
def _detect_mode(self):
|
if self.ads:
|
||||||
ok_mask = 0x00
|
log.info(f"detected {self._tic.name()}")
|
||||||
tic_map = { TIC_STX: 0x01,
|
return mode
|
||||||
TIC_ETX: 0x02,
|
log.error("no valid frame detected")
|
||||||
TIC_SGR: 0x04,
|
|
||||||
TIC_EGR: 0x08,
|
|
||||||
b'\x09': 0x10 } # TODO
|
|
||||||
|
|
||||||
nb_reset = 0
|
|
||||||
while c := self.device.get_char():
|
|
||||||
ok = tic_map.get(c, 0)
|
|
||||||
if ok_mask or ok == 0x01:
|
|
||||||
ok_mask = ok_mask | ok
|
|
||||||
if ok_mask == 0x1f:
|
|
||||||
log.info(f"Standard mode detected")
|
|
||||||
self.mode = TIC_MODE_STD
|
|
||||||
self._tic = tic_standard.TicStandard()
|
|
||||||
return self.mode
|
|
||||||
if ok_mask == 0x0f:
|
|
||||||
log.info(f"Historiqual mode detected")
|
|
||||||
self.mode = TIC_MODE_HIS
|
|
||||||
self._tic = tic_hist.TicHist()
|
|
||||||
return self.mode
|
|
||||||
if not ok and (c < b' ' or c > b'\x7f'):
|
|
||||||
log.debug(f"bad char: {c}")
|
|
||||||
ok_mask = 0x00
|
|
||||||
nb_reset = nb_reset + 1
|
|
||||||
if nb_reset >= 20:
|
|
||||||
break
|
|
||||||
log.debug("Timeout/EOF")
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_frame(self):
|
def get_frame(self):
|
||||||
@ -165,7 +159,8 @@ class Tic:
|
|||||||
|
|
||||||
def decode_group(self, group):
|
def decode_group(self, group):
|
||||||
msg = self._tic.decode_group(group)
|
msg = self._tic.decode_group(group)
|
||||||
if msg['label'] == 'ADSC':
|
log.debug(f"msg: {msg}")
|
||||||
|
if msg and msg.get('label') in ( 'ADSC', 'ADCO' ):
|
||||||
self.parse_ads(msg['value'])
|
self.parse_ads(msg['value'])
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
@ -184,6 +179,18 @@ class Tic:
|
|||||||
log.info(f"year: {self.device_year}")
|
log.info(f"year: {self.device_year}")
|
||||||
log.info(f"model: {self.device_model}")
|
log.info(f"model: {self.device_model}")
|
||||||
log.info(f"serial number: {self.device_serial}")
|
log.info(f"serial number: {self.device_serial}")
|
||||||
|
if self._cb_ads:
|
||||||
|
self._cb_ads(self.ads, self.device_manufacturer, self.device_year, self.device_model, self.device_serial)
|
||||||
|
|
||||||
|
def set_callback_ads(self, function):
|
||||||
|
self._cb_ads = function
|
||||||
|
if self.ads:
|
||||||
|
ads = self.ads
|
||||||
|
self.ads = None
|
||||||
|
self.parse_ads(self.ads)
|
||||||
|
|
||||||
|
def set_callback_msg(self, function):
|
||||||
|
self._cb_msg = function
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
while True:
|
while True:
|
||||||
@ -196,4 +203,8 @@ class Tic:
|
|||||||
continue
|
continue
|
||||||
msg = self.decode_group(group)
|
msg = self.decode_group(group)
|
||||||
log.info(msg)
|
log.info(msg)
|
||||||
|
if msg and self._cb_msg:
|
||||||
|
self._cb_msg(msg)
|
||||||
|
#if not self.device.is_serial():
|
||||||
|
# time.sleep(1)
|
||||||
|
|
||||||
|
11
tic2mqtt
11
tic2mqtt
@ -26,12 +26,17 @@ def main():
|
|||||||
|
|
||||||
logging.basicConfig(level=getattr(logging, args.log.upper()))
|
logging.basicConfig(level=getattr(logging, args.log.upper()))
|
||||||
|
|
||||||
tc = tic.Tic(args.input)
|
my_tic = tic.Tic(args.input)
|
||||||
tc.detect_mode()
|
if args.mode == "auto":
|
||||||
|
my_tic.detect_mode()
|
||||||
|
else:
|
||||||
|
my_tic.set_mode(args.mode)
|
||||||
|
|
||||||
mqtt = tic_mqtt.TicPublisher(args.broker)
|
mqtt = tic_mqtt.TicPublisher(args.broker)
|
||||||
|
my_tic.set_callback_ads(mqtt.set_ads)
|
||||||
|
my_tic.set_callback_msg(mqtt.send_msg)
|
||||||
|
|
||||||
tc.run()
|
my_tic.run()
|
||||||
|
|
||||||
if mqtt:
|
if mqtt:
|
||||||
mqtt.close()
|
mqtt.close()
|
||||||
|
49
tic_hist.py
49
tic_hist.py
@ -6,18 +6,40 @@ log = logging.getLogger(__name__)
|
|||||||
TIC_SEP_HIS = b'\x20'
|
TIC_SEP_HIS = b'\x20'
|
||||||
|
|
||||||
msgs = {
|
msgs = {
|
||||||
'ADCO': { 'len': 12, 'value': 'adsc' },
|
'ADCO': { 'len': 12, },
|
||||||
'OPTARIF': { 'len': 4 },
|
'OPTARIF': { 'len': 4 },
|
||||||
'ISOUSC': { 'len': 2, 'value': 'num' },
|
'ISOUSC': { 'len': 2, 'unit': 'A' },
|
||||||
'HCHC': { 'len': 9, 'value': 'num' },
|
'BASE': { 'len': 9, 'unit': 'Wh' },
|
||||||
'HCHP': { 'len': 9, 'value': 'num' },
|
'HCHC': { 'len': 9, 'unit': 'Wh' },
|
||||||
|
'HCHP': { 'len': 9, 'unit': 'Wh' },
|
||||||
|
'EJPHN': { 'len': 9, 'unit': 'Wh' },
|
||||||
|
'EJPHPM': { 'len': 9, 'unit': 'Wh' },
|
||||||
|
'BBRHCJB': { 'len': 9, 'unit': 'Wh' },
|
||||||
|
'BBRHPJB': { 'len': 9, 'unit': 'Wh' },
|
||||||
|
'BBRHCJW': { 'len': 9, 'unit': 'Wh' },
|
||||||
|
'BBRHPJW': { 'len': 9, 'unit': 'Wh' },
|
||||||
|
'BBRHCJR': { 'len': 9, 'unit': 'Wh' },
|
||||||
|
'BBRHPJR': { 'len': 9, 'unit': 'Wh' },
|
||||||
|
'PEJP': { 'len': 9, 'unit': 'min' },
|
||||||
'PTEC': { 'len': 4 },
|
'PTEC': { 'len': 4 },
|
||||||
'IINST': { 'len': 3, 'value': 'num' },
|
'DEMAIN': { 'len': 9 },
|
||||||
'ADPS': { 'len': 3, 'value': 'num' },
|
'IINST': { 'len': 3, 'unit': 'A' },
|
||||||
'IMAX': { 'len': 3, 'value': 'num' },
|
'IINST1': { 'len': 3, 'unit': 'A' },
|
||||||
'PAPP': { 'len': 5, 'value': 'num' },
|
'IINST2': { 'len': 3, 'unit': 'A' },
|
||||||
|
'IINST3': { 'len': 3, 'unit': 'A' },
|
||||||
|
'ADPS': { 'len': 3, 'unit': 'A' },
|
||||||
|
'IMAX': { 'len': 3, 'unit': 'A' },
|
||||||
|
'IMAX1': { 'len': 3, 'unit': 'A' },
|
||||||
|
'IMAX2': { 'len': 3, 'unit': 'A' },
|
||||||
|
'IMAX3': { 'len': 3, 'unit': 'A' },
|
||||||
|
'PMAX': { 'len': 5, 'unit': 'W' },
|
||||||
|
'PAPP': { 'len': 5, 'unit': 'VA' },
|
||||||
'HHPHC': { 'len': 1 },
|
'HHPHC': { 'len': 1 },
|
||||||
'MOTDETAT': { 'len': 6, 'value': 'num' },
|
'MOTDETAT': { 'len': 6 },
|
||||||
|
'PPOT': { 'len': 2 },
|
||||||
|
'ADIR1': { 'len': 3, 'unit': 'A' },
|
||||||
|
'ADIR2': { 'len': 3, 'unit': 'A' },
|
||||||
|
'ADIR3': { 'len': 3, 'unit': 'A' },
|
||||||
}
|
}
|
||||||
|
|
||||||
class TicHist:
|
class TicHist:
|
||||||
@ -25,6 +47,9 @@ class TicHist:
|
|||||||
self.sep = TIC_SEP_HIS.decode('ascii')
|
self.sep = TIC_SEP_HIS.decode('ascii')
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def name(self):
|
||||||
|
return "mode historique"
|
||||||
|
|
||||||
def check_sum(self, group):
|
def check_sum(self, group):
|
||||||
checksum = group[-1]
|
checksum = group[-1]
|
||||||
sum = 0
|
sum = 0
|
||||||
@ -49,8 +74,8 @@ class TicHist:
|
|||||||
if len(value) != msgs[label]['len']:
|
if len(value) != msgs[label]['len']:
|
||||||
log.warning(f'bad value length: {group}')
|
log.warning(f'bad value length: {group}')
|
||||||
return None
|
return None
|
||||||
value_type = msgs[label].get('value', None)
|
unit = msgs[label].get('unit')
|
||||||
if value_type == 'num':
|
if unit:
|
||||||
try:
|
try:
|
||||||
value = int(value)
|
value = int(value)
|
||||||
except:
|
except:
|
||||||
@ -61,5 +86,7 @@ class TicHist:
|
|||||||
|
|
||||||
msg['label'] = label
|
msg['label'] = label
|
||||||
msg['value'] = value
|
msg['value'] = value
|
||||||
|
if unit:
|
||||||
|
msg['unit'] = unit
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
|
112
tic_mqtt.py
112
tic_mqtt.py
@ -1,8 +1,29 @@
|
|||||||
import paho.mqtt.client as mqtt
|
import paho.mqtt.client as mqtt
|
||||||
|
import time
|
||||||
|
import json
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
state_class_from_unit = {
|
||||||
|
'Wh': 'total_increasing',
|
||||||
|
'VArh': 'power',
|
||||||
|
'A': 'measurement',
|
||||||
|
'V': 'measurement',
|
||||||
|
'kVA': 'measurement',
|
||||||
|
'VA': 'measurement',
|
||||||
|
'W': 'measurement',
|
||||||
|
}
|
||||||
|
|
||||||
|
device_class_from_unit = {
|
||||||
|
'Wh': 'energy',
|
||||||
|
'VArh': 'power',
|
||||||
|
'A': 'current',
|
||||||
|
'V': 'voltage',
|
||||||
|
'kVA': 'apparent_power',
|
||||||
|
'VA': 'apparent_power',
|
||||||
|
'W': 'power',
|
||||||
|
}
|
||||||
|
|
||||||
class TicPublisher:
|
class TicPublisher:
|
||||||
def __init__(self, hostname=None, port=1883):
|
def __init__(self, hostname=None, port=1883):
|
||||||
@ -11,9 +32,100 @@ class TicPublisher:
|
|||||||
self.client = mqtt.Client()
|
self.client = mqtt.Client()
|
||||||
self.client.connect(hostname, port)
|
self.client.connect(hostname, port)
|
||||||
#self.client.loop_start()
|
#self.client.loop_start()
|
||||||
|
self._ads = None
|
||||||
|
self._manufacturer = None
|
||||||
|
self._year = None
|
||||||
|
self._model = None
|
||||||
|
self._serial = None
|
||||||
|
self._last_ts = {}
|
||||||
|
self._ha_config = {}
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
if self.client:
|
if self.client:
|
||||||
#self.client.loop_stop()
|
#self.client.loop_stop()
|
||||||
self.client = None
|
self.client = None
|
||||||
|
|
||||||
|
def set_ads(self, ads, manufacturer, year, model, serial):
|
||||||
|
log.debug(f"ads: {ads} manufacturer: {manufacturer} year: {year} model: {model} serial: {serial}")
|
||||||
|
self._ads = ads
|
||||||
|
self._manufacturer = manufacturer
|
||||||
|
self._year = year
|
||||||
|
self._model = model
|
||||||
|
self._serial = serial
|
||||||
|
|
||||||
|
def get_topic(self, label):
|
||||||
|
label = label.replace('+', 'PLUS').replace('-', 'MOINS')
|
||||||
|
topic = f"tic/{self._ads}/{label}"
|
||||||
|
return topic
|
||||||
|
|
||||||
|
def send_ha_config(self, msg, topic):
|
||||||
|
if not self._ads:
|
||||||
|
return
|
||||||
|
label = msg.get('label')
|
||||||
|
unit = msg.get('unit')
|
||||||
|
device_class = device_class_from_unit.get(unit) if unit else None
|
||||||
|
state_class = state_class_from_unit.get(unit) if unit else None
|
||||||
|
unique_id = f"tic_{self._ads}_{label.replace('+','PLUS').replace('-','MOINS')}"
|
||||||
|
node_id = f"tic"
|
||||||
|
object_id = unique_id
|
||||||
|
|
||||||
|
config_topic = f"homeassistant/sensor/{node_id}/{object_id}/config"
|
||||||
|
config = {
|
||||||
|
'unique_id': unique_id,
|
||||||
|
'name': label,
|
||||||
|
'state_topic': topic,
|
||||||
|
'value_template': "{% if 'value' in value_json %}{{ value_json.value }}{% endif %}",
|
||||||
|
'device_class': device_class,
|
||||||
|
'unit_of_measurement': unit,
|
||||||
|
'device': {
|
||||||
|
'identifiers': [ f'tic_{self._ads}' ],
|
||||||
|
'manufacturer': self._manufacturer,
|
||||||
|
'model': self._model,
|
||||||
|
'name': 'Tic Enedis',
|
||||||
|
},
|
||||||
|
'origin': {
|
||||||
|
'name': 'tic2mqtt',
|
||||||
|
'sw_version': "0.1",
|
||||||
|
'support_url': "https://git.grandou.net/gilles/tic2mqtt",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if unit:
|
||||||
|
config['unit_of_measurement'] = unit
|
||||||
|
if device_class:
|
||||||
|
config['device_class'] = device_class
|
||||||
|
if state_class:
|
||||||
|
config['state_class'] = state_class
|
||||||
|
|
||||||
|
log.debug(f"HA config topic: {config_topic}")
|
||||||
|
log.debug(f"HA config: {config}")
|
||||||
|
result = self.client.publish(config_topic, json.dumps(config), retain=True)
|
||||||
|
|
||||||
|
def send_msg(self, msg):
|
||||||
|
log.debug(f"msg: {msg}")
|
||||||
|
if not self.client:
|
||||||
|
return
|
||||||
|
if not self._ads:
|
||||||
|
return
|
||||||
|
if msg.get('label') is None:
|
||||||
|
return
|
||||||
|
if msg.get('value') is None:
|
||||||
|
return
|
||||||
|
ts = time.time()
|
||||||
|
label = msg.get('label')
|
||||||
|
value = msg.get('value')
|
||||||
|
unit = msg.get('unit')
|
||||||
|
if self._last_ts.get(label):
|
||||||
|
if ts < self._last_ts[label]['ts'] + 60 and value == self._last_ts[label]['value']:
|
||||||
|
log.debug(f"skip msg {label} {value}")
|
||||||
|
return
|
||||||
|
self._last_ts[label] = { 'value': value, 'ts': ts }
|
||||||
|
topic = self.get_topic(label)
|
||||||
|
if not self._ha_config.get('label'):
|
||||||
|
self.send_ha_config(msg, topic)
|
||||||
|
_msg = { 'value': msg['value'] }
|
||||||
|
if msg.get('date'):
|
||||||
|
_msg['date'] = msg['date']
|
||||||
|
log.debug(f"topic: {topic} msg: {_msg}")
|
||||||
|
result = self.client.publish(topic, json.dumps(_msg))
|
||||||
|
|
||||||
|
|
||||||
|
117
tic_standard.py
117
tic_standard.py
@ -8,61 +8,61 @@ log = logging.getLogger(__name__)
|
|||||||
TIC_SEP_STD = b'\x09'
|
TIC_SEP_STD = b'\x09'
|
||||||
|
|
||||||
msgs = {
|
msgs = {
|
||||||
'ADSC': { 'len': 12, 'value': 'adsc' },
|
'ADSC': { 'len': 12 },
|
||||||
'VTIC': { 'len': 2, 'value': 'num' },
|
'VTIC': { 'len': 2 },
|
||||||
'DATE': { 'len': 0 },
|
'DATE': { 'len': 0 },
|
||||||
'NGTF': { 'len': 16 },
|
'NGTF': { 'len': 16 },
|
||||||
'LTARF': { 'len': 16 },
|
'LTARF': { 'len': 16 },
|
||||||
'EAST': { 'len': 9, 'value': 'num' },
|
'EAST': { 'len': 9, 'unit': 'Wh' },
|
||||||
'EASF01': { 'len': 9, 'value': 'num' },
|
'EASF01': { 'len': 9, 'unit': 'Wh' },
|
||||||
'EASF02': { 'len': 9, 'value': 'num' },
|
'EASF02': { 'len': 9, 'unit': 'Wh' },
|
||||||
'EASF03': { 'len': 9, 'value': 'num' },
|
'EASF03': { 'len': 9, 'unit': 'Wh' },
|
||||||
'EASF04': { 'len': 9, 'value': 'num' },
|
'EASF04': { 'len': 9, 'unit': 'Wh' },
|
||||||
'EASF05': { 'len': 9, 'value': 'num' },
|
'EASF05': { 'len': 9, 'unit': 'Wh' },
|
||||||
'EASF06': { 'len': 9, 'value': 'num' },
|
'EASF06': { 'len': 9, 'unit': 'Wh' },
|
||||||
'EASF07': { 'len': 9, 'value': 'num' },
|
'EASF07': { 'len': 9, 'unit': 'Wh' },
|
||||||
'EASF08': { 'len': 9, 'value': 'num' },
|
'EASF08': { 'len': 9, 'unit': 'Wh' },
|
||||||
'EASF09': { 'len': 9, 'value': 'num' },
|
'EASF09': { 'len': 9, 'unit': 'Wh' },
|
||||||
'EASF10': { 'len': 9, 'value': 'num' },
|
'EASF10': { 'len': 9, 'unit': 'Wh' },
|
||||||
'EASD01': { 'len': 9, 'value': 'num' },
|
'EASD01': { 'len': 9, 'unit': 'Wh' },
|
||||||
'EASD02': { 'len': 9, 'value': 'num' },
|
'EASD02': { 'len': 9, 'unit': 'Wh' },
|
||||||
'EASD03': { 'len': 9, 'value': 'num' },
|
'EASD03': { 'len': 9, 'unit': 'Wh' },
|
||||||
'EASD04': { 'len': 9, 'value': 'num' },
|
'EASD04': { 'len': 9, 'unit': 'Wh' },
|
||||||
'EAIT': { 'len': 9, 'value': 'num' },
|
'EAIT': { 'len': 9, 'unit': 'Wh' },
|
||||||
'ERQ1': { 'len': 9, 'value': 'num' },
|
'ERQ1': { 'len': 9, 'unit': 'VArh' },
|
||||||
'ERQ2': { 'len': 9, 'value': 'num' },
|
'ERQ2': { 'len': 9, 'unit': 'VArh' },
|
||||||
'ERQ3': { 'len': 9, 'value': 'num' },
|
'ERQ3': { 'len': 9, 'unit': 'VArh' },
|
||||||
'ERQ4': { 'len': 9, 'value': 'num' },
|
'ERQ4': { 'len': 9, 'unit': 'VArh' },
|
||||||
'IRMS1': { 'len': 3, 'value': 'num' },
|
'IRMS1': { 'len': 3, 'unit': 'A' },
|
||||||
'IRMS2': { 'len': 3, 'value': 'num' },
|
'IRMS2': { 'len': 3, 'unit': 'A' },
|
||||||
'IRMS3': { 'len': 3, 'value': 'num' },
|
'IRMS3': { 'len': 3, 'unit': 'A' },
|
||||||
'URMS1': { 'len': 3, 'value': 'num' },
|
'URMS1': { 'len': 3, 'unit': 'V' },
|
||||||
'URMS2': { 'len': 3, 'value': 'num' },
|
'URMS2': { 'len': 3, 'unit': 'V' },
|
||||||
'URMS3': { 'len': 3, 'value': 'num' },
|
'URMS3': { 'len': 3, 'unit': 'V' },
|
||||||
'PREF': { 'len': 2, 'value': 'num' },
|
'PREF': { 'len': 2, 'unit': 'kVA' },
|
||||||
'PCOUP': { 'len': 2, 'value': 'num' },
|
'PCOUP': { 'len': 2, 'unit': 'kVA' },
|
||||||
'SINSTS': { 'len': 5, 'value': 'num' },
|
'SINSTS': { 'len': 5, 'unit': 'VA' },
|
||||||
'SINST1': { 'len': 5, 'value': 'num' },
|
'SINST1': { 'len': 5, 'unit': 'VA' },
|
||||||
'SINST2': { 'len': 5, 'value': 'num' },
|
'SINST2': { 'len': 5, 'unit': 'VA' },
|
||||||
'SINST3': { 'len': 5, 'value': 'num' },
|
'SINST3': { 'len': 5, 'unit': 'VA' },
|
||||||
'SMAXSN': { 'len': 5, 'value': 'num' },
|
'SMAXSN': { 'len': 5, 'unit': 'VA' },
|
||||||
'SMAXSN1': { 'len': 5, 'value': 'num' },
|
'SMAXSN1': { 'len': 5, 'unit': 'VA' },
|
||||||
'SMAXSN2': { 'len': 5, 'value': 'num' },
|
'SMAXSN2': { 'len': 5, 'unit': 'VA' },
|
||||||
'SMAXSN3': { 'len': 5, 'value': 'num' },
|
'SMAXSN3': { 'len': 5, 'unit': 'VA' },
|
||||||
'SMAXSN-1': { 'len': 5, 'value': 'num' },
|
'SMAXSN-1': { 'len': 5, 'unit': 'VA' },
|
||||||
'SMAXSN1-1': { 'len': 5, 'value': 'num' },
|
'SMAXSN1-1': { 'len': 5, 'unit': 'VA' },
|
||||||
'SMAXSN2-1': { 'len': 5, 'value': 'num' },
|
'SMAXSN2-1': { 'len': 5, 'unit': 'VA' },
|
||||||
'SMAXSN3-1': { 'len': 5, 'value': 'num' },
|
'SMAXSN3-1': { 'len': 5, 'unit': 'VA' },
|
||||||
'SINSTI': { 'len': 5, 'value': 'num' },
|
'SINSTI': { 'len': 5, 'unit': 'VA' },
|
||||||
'SMAXIN': { 'len': 5, 'value': 'num' },
|
'SMAXIN': { 'len': 5, 'unit': 'VA' },
|
||||||
'SMAXIN-1': { 'len': 5, 'value': 'num' },
|
'SMAXIN-1': { 'len': 5, 'unit': 'VA' },
|
||||||
'CCASN': { 'len': 5, 'value': 'num' },
|
'CCASN': { 'len': 5, 'unit': 'W' },
|
||||||
'CCASN-1': { 'len': 5, 'value': 'num' },
|
'CCASN-1': { 'len': 5, 'unit': 'W' },
|
||||||
'CCAIN': { 'len': 5, 'value': 'num' },
|
'CCAIN': { 'len': 5, 'unit': 'W' },
|
||||||
'CCAIN-1': { 'len': 5, 'value': 'num' },
|
'CCAIN-1': { 'len': 5, 'unit': 'W' },
|
||||||
'UMOY1': { 'len': 3, 'value': 'num' },
|
'UMOY1': { 'len': 3, 'unit': 'V' },
|
||||||
'UMOY2': { 'len': 3, 'value': 'num' },
|
'UMOY2': { 'len': 3, 'unit': 'V' },
|
||||||
'UMOY3': { 'len': 3, 'value': 'num' },
|
'UMOY3': { 'len': 3, 'unit': 'V' },
|
||||||
'STGE': { 'len': 8 },
|
'STGE': { 'len': 8 },
|
||||||
'DPM1': { 'len': 2 },
|
'DPM1': { 'len': 2 },
|
||||||
'FPM1': { 'len': 2 },
|
'FPM1': { 'len': 2 },
|
||||||
@ -93,6 +93,9 @@ class TicStandard:
|
|||||||
}
|
}
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def name(self):
|
||||||
|
return "mode standard"
|
||||||
|
|
||||||
def check_sum(self, group):
|
def check_sum(self, group):
|
||||||
checksum = group[-1]
|
checksum = group[-1]
|
||||||
sum = 0
|
sum = 0
|
||||||
@ -120,8 +123,9 @@ class TicStandard:
|
|||||||
if len(value) != msgs[label]['len']:
|
if len(value) != msgs[label]['len']:
|
||||||
log.warning(f'bad value length: {group}')
|
log.warning(f'bad value length: {group}')
|
||||||
return None
|
return None
|
||||||
|
unit = msgs[label].get('unit')
|
||||||
value_type = msgs[label].get('value', None)
|
value_type = msgs[label].get('value', None)
|
||||||
if value_type == 'num':
|
if unit:
|
||||||
try:
|
try:
|
||||||
value = int(value)
|
value = int(value)
|
||||||
except:
|
except:
|
||||||
@ -129,11 +133,16 @@ class TicStandard:
|
|||||||
return None
|
return None
|
||||||
else:
|
else:
|
||||||
value = re.sub('\s\s+', ' ', value).strip()
|
value = re.sub('\s\s+', ' ', value).strip()
|
||||||
|
if not len(value):
|
||||||
|
value = None
|
||||||
|
|
||||||
msg['label'] = label
|
msg['label'] = label
|
||||||
msg['value'] = value
|
if value is not None:
|
||||||
|
msg['value'] = value
|
||||||
if date:
|
if date:
|
||||||
msg['date'] = date
|
msg['date'] = date
|
||||||
|
if unit:
|
||||||
|
msg['unit'] = unit
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
def parse_date(self, str):
|
def parse_date(self, str):
|
||||||
|
Loading…
Reference in New Issue
Block a user