jsonifying register file done so far

This commit is contained in:
Wolfgang Hottgenroth 2019-07-16 14:11:04 +02:00
parent 2665fdd5e3
commit d97b7469fe
Signed by: wn
GPG Key ID: 6C1E5E531E0D5D7F
6 changed files with 203 additions and 51 deletions

14
snippets/test9.py Normal file
View File

@ -0,0 +1,14 @@
class A(object):
def __init__(self):
self.a = 1
def x(self):
return self.a
class B(A):
def __init__(self):
self.a = 2
def x(self):
return self.a
def y(self):
return super().x()

View File

@ -309,23 +309,17 @@ class CmdInterpreter(cmd.Cmd):
self.__println("DO NOT FORGET TO SAVE AFTERWARDS!") self.__println("DO NOT FORGET TO SAVE AFTERWARDS!")
def do_save(self, arg): def do_save(self, arg):
for i in self.registers: RegisterDatapoint.saveRegisterFile(self.registers, self.config.registerFile)
self.logger.warn("{0!s}: {1!s}".format(i, i.__dict__))
with open(self.config.registerFile, 'wb') as f:
pickle.dump(self.registers, f)
def help_save(self): def help_save(self):
self.__println("Usage: save") self.__println("Usage: save")
self.__println("Saves a modified register list into the register file.") self.__println("Saves a modified register list into the register file.")
def do_load(self, arg): def do_load(self, arg):
registers = None
with open(self.config.registerFile, 'rb') as f:
registers = pickle.load(f)
try: try:
RegisterDatapoint.checkRegisterList(registers) registers = RegisterDatapoint.loadRegisterList(self.config.registerFile)
self.registers = registers self.registers = registers
except ValueError as e: except Exception as e:
self.__println("Unable to load register list: {0!s}".format(e)) self.__println("Unable to load register list: {0!s}".format(e))
def help_load(self): def help_load(self):

View File

@ -3,17 +3,44 @@ from pymodbus.pdu import ExceptionResponse
from pymodbus.exceptions import ModbusIOException from pymodbus.exceptions import ModbusIOException
import MqttProcessor import MqttProcessor
import logging import logging
import json
import pickle import pickle
class JsonifyEncoder(json.JSONEncoder):
def default(self, o):
res = None
try:
res = o.jsonify()
except (TypeError, AttributeError):
if type(o) == datetime.timedelta:
res = o.total_seconds()
else:
res = super().default(o)
return res
def datapointObjectHook(j):
if type(j) == dict and 'type' in j and 'args' in j:
klass = eval(j['type'])
o = klass(**j['args'])
return o
else:
return j
class DatapointException(Exception): pass class DatapointException(Exception): pass
class AbstractModbusDatapoint(object): class AbstractModbusDatapoint(object):
def __init__(self, label=None, unit=None, address=None, count=None, scanRate=None): def __init__(self, label=None, unit=None, address=None, count=None, scanRate=None):
self.argList = ['label', 'unit', 'address', 'count', 'scanRate']
self.label = label self.label = label
self.unit = unit self.unit = unit
self.address = address self.address = address
self.count = count self.count = count
if type(scanRate) == float:
self.scanRate = datetime.timedelta(seconds=scanRate)
else:
self.scanRate = scanRate self.scanRate = scanRate
self.type = 'abstract data point' self.type = 'abstract data point'
self.enqueued = False self.enqueued = False
@ -32,14 +59,21 @@ class AbstractModbusDatapoint(object):
self.scanRate, self.enqueued, self.lastContact, self.scanRate, self.enqueued, self.lastContact,
self.errorCount, self.processCount)) self.errorCount, self.processCount))
def jsonify(self):
return {'type':self.__class__.__name__,
'args': { k: getattr(self, k) for k in self.argList }
}
def process(self, client): def process(self, client):
raise NotImplementedError raise NotImplementedError
class HoldingRegisterDatapoint(AbstractModbusDatapoint): class HoldingRegisterDatapoint(AbstractModbusDatapoint):
def __init__(self, label=None, unit=None, address=None, count=None, scanRate=None, def __init__(self, label=None, unit=None, address=None, count=None, scanRate=None,
publishTopic=None, subscribeTopic=None, feedbackTopic=None): publishTopic=None, subscribeTopic=None, feedbackTopic=None):
super().__init__(label, unit, address, count, scanRate) super().__init__(label, unit, address, count, scanRate)
self.argList = self.argList + ['publishTopic', 'subscribeTopic', 'feedbackTopic']
self.publishTopic = publishTopic self.publishTopic = publishTopic
self.subscribeTopic = subscribeTopic self.subscribeTopic = subscribeTopic
self.feedbackTopic = feedbackTopic self.feedbackTopic = feedbackTopic
@ -79,6 +113,7 @@ class HoldingRegisterDatapoint(AbstractModbusDatapoint):
class ReadOnlyDatapoint(AbstractModbusDatapoint): class ReadOnlyDatapoint(AbstractModbusDatapoint):
def __init__(self, label=None, unit=None, address=None, count=None, scanRate=None, updateOnly=None, publishTopic=None): def __init__(self, label=None, unit=None, address=None, count=None, scanRate=None, updateOnly=None, publishTopic=None):
super().__init__(label, unit, address, count, scanRate) super().__init__(label, unit, address, count, scanRate)
self.argList = self.argList + ['updateOnly', 'publishTopic']
self.updateOnly = updateOnly self.updateOnly = updateOnly
self.lastValue = None self.lastValue = None
self.publishTopic = publishTopic self.publishTopic = publishTopic
@ -137,39 +172,14 @@ class DiscreteInputDatapoint(ReadOnlyDatapoint):
def loadRegisterList(registerList): def saveRegisterList(registerList, registerListFile):
# Load, check and auto-update registers file js = json.dumps(registerList, cls=JsonifyEncoder, sort_keys=True, indent=4)
with open(registerListFile, 'w') as f:
with open(registerList, 'rb') as f: f.write(js)
datapoints = pickle.load(f)
checkRegisterList(datapoints)
newDatapoints = []
for dp in datapoints:
ndp = type(dp)()
for k,v in dp.__dict__.items():
ndp.__dict__[k] = v
newDatapoints.append(ndp)
logging.getLogger('loadRegisterList').debug("Datapoint loaded: {0!s}".format(ndp))
checkRegisterList(newDatapoints, reset=True)
with open(registerList, 'wb') as f:
pickle.dump(newDatapoints, f)
return newDatapoints
def checkRegisterList(registers, reset=False):
for r in registers:
if not isinstance(r, AbstractModbusDatapoint):
raise ValueError('Entry in register list {0!s} is not derived from class AbstractModbusDatapoint'.format(r))
else:
if reset:
r.errorCount = 0
r.processCount = 0
r.enqueued = False
def loadRegisterList(registerListFile):
with open(registerListFile, 'r') as f:
js = f.read()
registerList = json.loads(js, object_hook=datapointObjectHook)
return registerList

6
src/loadRegisterFile.py Normal file
View File

@ -0,0 +1,6 @@
import RegisterDatapoint
registers = RegisterDatapoint.loadRegisterList('registers.json')
for r in registers:
print("{0!s}".format(r))

129
src/registers.json Normal file
View File

@ -0,0 +1,129 @@
[
{
"args": {
"address": 1,
"count": 1,
"label": "Temperature",
"publishTopic": "Pub/Temperature",
"scanRate": 60.0,
"unit": 5,
"updateOnly": false
},
"type": "InputRegisterDatapoint"
},
{
"args": {
"address": 2,
"count": 1,
"label": "Humidity",
"publishTopic": "Pub/Humidity",
"scanRate": null,
"unit": 5,
"updateOnly": false
},
"type": "InputRegisterDatapoint"
},
{
"args": {
"address": 0,
"count": 1,
"label": "Switches",
"publishTopic": "Pub/Switches",
"scanRate": 60.0,
"unit": 4,
"updateOnly": false
},
"type": "DiscreteInputDatapoint"
},
{
"args": {
"address": 40010,
"count": 2,
"feedbackTopic": null,
"label": "Counter1",
"publishTopic": "Pub/Counter1",
"scanRate": 60.0,
"subscribeTopic": null,
"unit": 4
},
"type": "HoldingRegisterDatapoint"
},
{
"args": {
"address": 40012,
"count": 2,
"feedbackTopic": null,
"label": "Counter2",
"publishTopic": "Pub/Counter2",
"scanRate": 60.0,
"subscribeTopic": null,
"unit": 4
},
"type": "HoldingRegisterDatapoint"
},
{
"args": {
"address": 40014,
"count": 2,
"feedbackTopic": null,
"label": "Counter3",
"publishTopic": "Pub/Counter3",
"scanRate": 60.0,
"subscribeTopic": null,
"unit": 4
},
"type": "HoldingRegisterDatapoint"
},
{
"args": {
"address": 40016,
"count": 2,
"feedbackTopic": null,
"label": "Counter4",
"publishTopic": "Pub/Counter4",
"scanRate": 60.0,
"subscribeTopic": null,
"unit": 4
},
"type": "HoldingRegisterDatapoint"
},
{
"args": {
"address": 40001,
"count": 1,
"feedbackTopic": null,
"label": "Version",
"publishTopic": "Pub/Version",
"scanRate": 1.0,
"subscribeTopic": null,
"unit": 4
},
"type": "HoldingRegisterDatapoint"
},
{
"args": {
"address": 40001,
"count": 1,
"feedbackTopic": null,
"label": "Version",
"publishTopic": "Pub/Version",
"scanRate": 10.0,
"subscribeTopic": null,
"unit": 4
},
"type": "HoldingRegisterDatapoint"
},
{
"args": {
"address": 40001,
"count": 1,
"feedbackTopic": "FB/Version",
"label": "Version_W",
"publishTopic": null,
"scanRate": 0.0,
"subscribeTopic": "Sub/Version",
"unit": 4
},
"type": "HoldingRegisterDatapoint"
}
]

View File

@ -1,14 +1,12 @@
import datetime import datetime
import RegisterDatapoint import RegisterDatapoint
import pickle import pickle
import json
with open('registers.pkl', 'rb') as f: with open('registers.pkl', 'rb') as f:
datapoints = pickle.load(f) datapoints = pickle.load(f)
RegisterDatapoint.checkRegisterList(datapoints, reset=True)
newDatapoints = [] newDatapoints = []
for dp in datapoints: for dp in datapoints:
ndp = type(dp)() ndp = type(dp)()
@ -17,9 +15,10 @@ for dp in datapoints:
ndp.__dict__[k] = v ndp.__dict__[k] = v
newDatapoints.append(ndp) newDatapoints.append(ndp)
RegisterDatapoint.checkRegisterList(newDatapoints, reset=True)
with open('registers.pkl', 'wb') as f:
pickle.dump(newDatapoints, f)
js = json.dumps(newDatapoints, cls=RegisterDatapoint.JsonifyEncoder, sort_keys=True, indent=4)
print(js)
RegisterDatapoint.saveRegisterList(newDatapoints, 'registers.json')