Files
adminandClaude Opus 5 79843aa2ae SolarManager unter Versionsverwaltung
Erster Stand der Hintergrundprozesse, die auf der Synology unter
/volume1/homes/wagner/SolarManager laufen: der Manager selbst, die Sammler
je Geraet, die MQTT-Bruecke, der Wecker und - neu hinzugezogen - der
AutoAction-Runner, der als Hintergrundprozess hierher gehoert und nicht ins
Web-Verzeichnis.

Zugangsdaten stehen nicht mehr im Quelltext, sondern in config.ini, die
nicht mit eingecheckt wird. Vorlage ist config.ini.example, gelesen wird sie
von konfig.py. Betroffen waren solarManager.py (Datenbank und Wattpilot),
zeit.py, gatherWaterData.py, wecker.py und skoda_testdaten.py, das sich das
Passwort bisher aus dem Quelltext eines anderen Moduls herausgesucht hat.

Die Kia-Anbindung ist mit dem Fahrzeug entfallen: kiaTest.py,
gatherCarData.py und hyundai_kia_connect_api sind nicht mehr dabei, ebenso
gatherInverterData.py, auf das nur noch eine auskommentierte Zeile zeigte.

Die mitgelieferten Bibliotheken bleiben im Repository - die NAS hat kein
pip, sie muessen neben den Skripten liegen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-02 20:46:59 +02:00

3337 lines
124 KiB
Python

import sunspec2.device as device
import sunspec2.mdef as mdef
import sunspec2.mb as mb
import pytest
@pytest.fixture
def model_705_data():
return {
"ID": 705,
"Ena": 1,
"CrvSt": 1,
"AdptCrvReq": 0,
"AdptCrvRslt": 0,
"NPt": 4,
"NCrv": 3,
"RvrtTms": 0,
"RvrtRem": 0,
"RvrtCrv": 0,
"V_SF": -2,
"DeptRef_SF": -2,
"Crv": [
{
"ActPt": 4,
"DeptRef": 1,
"Pri": 1,
"VRef": 1,
"VRefAuto": 0,
"VRefTms": 5,
"RspTms": 6,
"ReadOnly": 1,
"Pt": [
{
"V": 9200,
"Var": 3000
},
{
"V": 9670,
"Var": 0
},
{
"V": 10300,
"Var": 0
},
{
"V": 10700,
"Var": 3000
}
]
},
{
"ActPt": 4,
"DeptRef": 1,
"Pri": 1,
"VRef": 1,
"VRefAuto": 0,
"VRefTms": 5,
"RspTms": 6,
"ReadOnly": 0,
"Pt": [
{
"V": 9300,
"Var": 3000
},
{
"V": 9570,
"Var": 0
},
{
"V": 10200,
"Var": 0
},
{
"V": 10600,
"Var": 4000
}
]
},
{
"ActPt": 4,
"DeptRef": 1,
"Pri": 1,
"VRef": 1,
"VRefAuto": 0,
"VRefTms": 5,
"RspTms": 6,
"ReadOnly": 0,
"Pt": [
{
"V": 9400,
"Var": 2000
},
{
"V": 9570,
"Var": 0
},
{
"V": 10500,
"Var": 0
},
{
"V": 10800,
"Var": 2000
}
]
}
]
}
def test_get_model_info():
model_info = device.get_model_info(705)
assert model_info[0]['id'] == 705
assert model_info[1]
assert model_info[2] == 15
def test_check_group_count():
gdef = {'count': 'NPt'}
gdef2 = {'groups': [{'test': 'test'}, {'count': 'NPt'}]}
gdef3 = {'test1': 'test2', 'groups': [{'test3': 'test3'}, {'test4': 'test4'}]}
assert device.check_group_count(gdef) is True
assert device.check_group_count(gdef2) is True
assert device.check_group_count(gdef3) is False
def test_get_model_def():
with pytest.raises(mdef.ModelDefinitionError) as exc1:
device.get_model_def('z')
assert 'Invalid model id' in str(exc1.value)
with pytest.raises(Exception) as exc2:
device.get_model_def('000')
assert 'Model definition not found for model' in str(exc2.value)
assert device.get_model_def(704)['id'] == 704
def test_add_mappings():
group_def = {
"group": {
"groups": [
{
"name": "PFWInj",
"points": [
{
"access": "RW",
"desc": "Power factor setpoint when injecting active power.",
"label": "Power Factor (W Inj) ",
"mandatory": "O",
"name": "PF",
"sf": "PF_SF",
"type": "uint16"
},
],
"type": "sync"
},
{
"name": "PFWInjRvrt",
"points": [
{
"access": "RW",
"desc": "Reversion power factor setpoint when injecting active power.",
"label": "Reversion Power Factor (W Inj) ",
"mandatory": "O",
"name": "PF",
"sf": "PF_SF",
"type": "uint16"
}
],
"type": "sync"
}
],
"name": "DERCtlAC",
"points": [
{
"name": "ID",
"static": "S",
"type": "uint16",
"value": 704
}
],
"type": "group"
},
"id": 704
}
group_def_w_mappings = {
"group": {
"groups": [
{
"name": "PFWInj",
"points": [
{
"access": "RW",
"desc": "Power factor setpoint when injecting active power.",
"label": "Power Factor (W Inj) ",
"mandatory": "O",
"name": "PF",
"sf": "PF_SF",
"type": "uint16"
}
],
"type": "sync",
"point_defs": {
"PF": {
"access": "RW",
"desc": "Power factor setpoint when injecting active power.",
"label": "Power Factor (W Inj) ",
"mandatory": "O",
"name": "PF",
"sf": "PF_SF",
"type": "uint16"
}
},
"group_defs": {}
},
{
"name": "PFWInjRvrt",
"points": [
{
"access": "RW",
"desc": "Reversion power factor setpoint when injecting active power.",
"label": "Reversion Power Factor (W Inj) ",
"mandatory": "O",
"name": "PF",
"sf": "PF_SF",
"type": "uint16"
}
],
"type": "sync",
"point_defs": {
"PF": {
"access": "RW",
"desc": "Reversion power factor setpoint when injecting active power.",
"label": "Reversion Power Factor (W Inj) ",
"mandatory": "O",
"name": "PF",
"sf": "PF_SF",
"type": "uint16"
}
},
"group_defs": {}
}
],
"name": "DERCtlAC",
"points": [
{
"name": "ID",
"static": "S",
"type": "uint16",
"value": 704
}
],
"type": "group",
"point_defs": {
"ID": {
"name": "ID",
"static": "S",
"type": "uint16",
"value": 704
}
},
"group_defs": {
"PFWInj": {
"name": "PFWInj",
"points": [
{
"access": "RW",
"desc": "Power factor setpoint when injecting active power.",
"label": "Power Factor (W Inj) ",
"mandatory": "O",
"name": "PF",
"sf": "PF_SF",
"type": "uint16"
}
],
"type": "sync",
"point_defs": {
"PF": {
"access": "RW",
"desc": "Power factor setpoint when injecting active power.",
"label": "Power Factor (W Inj) ",
"mandatory": "O",
"name": "PF",
"sf": "PF_SF",
"type": "uint16"
}
},
"group_defs": {}
},
"PFWInjRvrt": {
"name": "PFWInjRvrt",
"points": [
{
"access": "RW",
"desc": "Reversion power factor setpoint when injecting active power.",
"label": "Reversion Power Factor (W Inj) ",
"mandatory": "O",
"name": "PF",
"sf": "PF_SF",
"type": "uint16"
}
],
"type": "sync",
"point_defs": {
"PF": {
"access": "RW",
"desc": "Reversion power factor setpoint when injecting active power.",
"label": "Reversion Power Factor (W Inj) ",
"mandatory": "O",
"name": "PF",
"sf": "PF_SF",
"type": "uint16"
}
},
"group_defs": {}
}
}
},
"id": 704
}
device.add_mappings(group_def['group'])
assert group_def == group_def_w_mappings
class TestPoint:
def test___init__(self):
p_def = {
"name": "Ena",
"type": "enum16",
"sf": 'test sf',
"static": "S"
}
p = device.Point(p_def)
assert p.model is None
assert p.pdef == p_def
assert p.info == mb.point_type_info[mdef.TYPE_ENUM16]
assert p.len == 1
assert p.offset == 0
assert p.value is None
assert p.dirty is False
assert p.sf == 'test sf'
assert p.sf_required is True
assert p.sf_value is None
assert p.static
def test__set_data(self):
p_def = {
"name": 'TestPoint',
"type": "uint16"
}
# bytes
p = device.Point(p_def)
p._set_data(b'\x00\x03')
assert p.value == 3
assert not p.dirty
# dict
data = {"TestPoint": 3}
p2 = device.Point(p_def)
p2._set_data(data)
assert p2.value == 3
def test_value_getter(self):
p_def = {
"name": "TestPoint",
"type": "uint16",
}
p = device.Point(p_def)
p.value = 4
assert p.value == 4
def test_value_setter(self):
p_def = {
"name": "TestPoint",
"type": "uint16",
}
p = device.Point(p_def)
p.value = 4
assert p.value == 4
def test_cvalue_getter(self):
p_def = {
"name": "TestPoint",
"type": "uint16",
"sf": "TestSF"
}
p = device.Point(p_def)
p.sf_required = True
p.sf_value = 3
p.value = 4
setattr(p, "static", True)
assert p.cvalue == 4000.0
p_sf = device.Point()
points = {'TestSF': p_sf}
m = device.Model()
setattr(m, 'points', points)
p2 = device.Point(p_def, model=m)
setattr(p2, "static", True)
p2.sf_value = -2
p2.cvalue = 1.16
assert p2.cvalue == 1.16
assert p2.value == 116
# test static true
p_sf = device.Point()
setattr(p_sf, "_value", 3)
points = {'TestSF': p_sf}
m = device.Model()
g = device.Group()
setattr(m, 'points', points)
setattr(g, 'points', points)
p5 = device.Point(p_def, model=m)
setattr(p5, "static", True)
setattr(p5, "group", g)
p5.value = 4
assert p5.cvalue == 4000.0
setattr(p_sf, "_value", 4)
assert p5.cvalue == 4000.0
# test static false
p_sf = device.Point()
setattr(p_sf, "_value", 3)
points = {'TestSF': p_sf}
m = device.Model()
g = device.Group()
setattr(m, 'points', points)
setattr(g, 'points', points)
p4 = device.Point(p_def, model=m)
setattr(p4, "group", g)
p4.value = 4
assert p4.cvalue == 4000.0
setattr(p_sf, "_value", 4)
assert p4.cvalue == 40000.0
def test_cvalue_setter(self):
p_def = {
"name": "TestPoint",
"type": "uint16"
}
p = device.Point(p_def)
p.sf_required = True
p.sf_value = 3
p.cvalue = 3000
assert p.value == 3
p_sf = device.Point()
points = {'TestSF': p_sf}
m = device.Model()
setattr(m, 'points', points)
p2 = device.Point(p_def, model=m)
p2.sf_value = -2
p2.cvalue = 1.38
assert p2.cvalue == 1.38
assert p2.value == 138
# test static true
p_def2 = {
"name": "TestPoint",
"type": "uint16",
"sf": "TestSF"
}
p_sf = device.Point()
setattr(p_sf, "_value", 3)
points = {'TestSF': p_sf}
m = device.Model()
g = device.Group()
setattr(m, 'points', points)
setattr(g, 'points', points)
p5 = device.Point(p_def2, model=m)
setattr(p5, "static", True)
setattr(p5, "group", g)
p5.cvalue = 4000.0
assert p5.value == 4
setattr(p_sf, "_value", 4)
p5.cvalue = 4000.0
assert p5.value == 4
# test static false
p_sf = device.Point()
setattr(p_sf, "_value", 3)
points = {'TestSF': p_sf}
m = device.Model()
g = device.Group()
setattr(m, 'points', points)
setattr(g, 'points', points)
p4 = device.Point(p_def2, model=m)
setattr(p4, "group", g)
p4.cvalue = 4000.0
assert p4.value == 4
setattr(p_sf, "_value", 2)
p4.cvalue = 4000.0
assert p4.value == 40
def test_get_value(self):
p_def = {
"access": "RW",
"desc": "Power factor setpoint when injecting active power.",
"label": "Power Factor (W Inj) ",
"name": "PF",
"type": "uint16",
}
p = device.Point(p_def)
setattr(p, "static", True)
p.value = 3
assert p.get_value() == 3
p2 = device.Point(p_def)
setattr(p2, "static", True)
assert p2.get_value() is None
# pdef w/ sf
pdef_sf = {
"name": "TestPoint",
"type": "uint16",
"sf": "TestSF"
}
# sf point
sf_p = {
"name": "TestSF",
"value": 3,
"type": "sunssf"
}
# computed
p_sf = device.Point(sf_p)
p_sf.value = 3
points = {}
points['TestSF'] = p_sf
m2 = device.Model()
setattr(m2, 'points', points)
g = device.Group()
setattr(g, 'points', points)
p9 = device.Point(pdef_sf, model=m2)
setattr(p9, "static", True)
p9.group = g
p9.value = 2020
assert p9.get_value(computed=True) == 2020000.0
p9.sf_value = -2
p9.cvalue = 1.16
assert p9.get_value(computed=True) == 1.16
assert p9.get_value() == 116
# computed exception
m3 = device.Model()
points2 = {}
setattr(m3, 'points', points2)
p10 = device.Point(pdef_sf, model=m3)
setattr(p10, "static", True)
g2 = device.Group()
setattr(g2, 'points', {})
p10.group = g2
p10.value = 2020
with pytest.raises(device.ModelError) as exc:
p10.get_value(computed=True)
assert 'Scale factor TestSF for point TestPoint not found' in str(exc.value)
def test_set_value(self):
p_def = {
"access": "RW",
"desc": "Power factor setpoint when injecting active power.",
"label": "Power Factor (W Inj) ",
"name": "PF",
"type": "uint16"
}
p = device.Point(p_def)
setattr(p, "static", True)
p.set_value(3)
assert p.value == 3
# test computed
pdef_computed = {
"name": "TestingComputed",
"type": "uint16",
"sf": "TestSF"
}
p_SF = device.Point()
p_SF.value = 2
points = {}
points['TestSF'] = p_SF
m = device.Model()
setattr(m, 'points', points)
p3 = device.Point(pdef_computed, model=m)
setattr(p3, "static", True)
g = device.Group
setattr(g, 'points', {})
p3.group = g
p3.set_value(1000, computed=True, dirty=True)
assert p3.value == 10
assert p3.dirty
# test exceptions
p2_sf = device.Point()
m2 = device.Model()
points2 = {}
points2['TestSF'] = p2_sf
setattr(m2, 'points', points2)
p4 = device.Point(pdef_computed, model=m2)
setattr(p4, "static", True)
p4.group = g
with pytest.raises(device.ModelError) as exc:
p4.set_value(1000, computed=True)
assert 'SF field TestSF value not initialized for point TestingComputed' in str(exc.value)
# test computed float rounding
p5 = device.Point(pdef_computed, model=m2)
setattr(p5, "static", True)
p5.sf_value = -2
p5.set_value(1.16, computed=True)
assert p5.get_value(computed=True) == 1.16
assert p5.get_value() == 116
def test_get_mb(self):
p_def = {
"name": "ESVLo",
"type": "uint16",
"sf": "TestSF"
}
p = device.Point(p_def)
setattr(p, "static", True)
p.value = 3
assert p.get_mb() == b'\x00\x03'
p.value = None
assert p.get_mb() == b'\xff\xff'
assert p.get_mb(computed=True) == b'\xff\xff'
# computed
p.value = 3
p.sf_required = True
p.sf_value = 4
assert p.get_mb(computed=True) == b'\x75\x30'
# test static true
p_sf = device.Point()
setattr(p_sf, "_value", 3)
points = {'TestSF': p_sf}
m = device.Model()
g = device.Group()
setattr(m, 'points', points)
setattr(g, 'points', points)
p2 = device.Point(p_def, model=m)
setattr(p2, "static", True)
setattr(p2, "group", g)
p2.value = 4
assert p2.get_mb(computed=True) == b'\x0f\xa0'
setattr(p_sf, "_value", 4)
assert p2.get_mb(computed=True) == b'\x0f\xa0'
# test static false
p_sf = device.Point()
setattr(p_sf, "_value", 3)
points = {'TestSF': p_sf}
m = device.Model()
g = device.Group()
setattr(m, 'points', points)
setattr(g, 'points', points)
p4 = device.Point(p_def, model=m)
setattr(p4, "group", g)
p4.value = 4
assert p4.get_mb(computed=True) == b'\x0f\xa0'
setattr(p_sf, "_value", 4)
assert p4.get_mb(computed=True) == b'\x9c\x40'
def test_set_mb(self):
p_def = {
"name": "ESVLo",
"type": "uint16",
}
m = device.Model()
g = device.Group()
g.points = {}
p3 = device.Point(p_def, m)
p3.group = g
p3.set_mb(None)
assert p3.model.error_info == "Error setting value for ESVLo: object of type 'NoneType' has no len()\n"
# exceptions
p_def2 = {
"name": "ESVLo",
"type": "uint16",
"sf": "TestSF"
}
p_sf = device.Point()
points = {}
points['TestSF'] = p_sf
setattr(m, 'points', points)
m.error_info = ''
p4 = device.Point(p_def2, model=m)
p4.group = g
p4.set_mb(b'\x00\x03', computed=True)
assert m.error_info == 'Error setting value for ESVLo: SF field TestSF value not initialized for point ESVLo\n'
del m.points['TestSF']
m.error_info = ''
p5 = device.Point(p_def2, model=m)
p5.group = g
p5.set_mb(b'\x00\x04', computed=True)
assert m.error_info == 'Error setting value for ESVLo: Scale factor TestSF for point ESVLo not found\n'
# test computed
pdef_computed = {
"name": "TestingComputed",
"type": "uint16",
"sf": "TestSF"
}
p_SF = device.Point()
p_SF.value = 2
points = {}
points['TestSF'] = p_SF
m = device.Model()
setattr(m, 'points', points)
p6 = device.Point(pdef_computed, model=m)
p6.group = g
p6.set_mb(b'\x0b\xb8', computed=True, dirty=True)
assert p6.value == 30
assert p6.dirty
# test static true
p_def2 = {
"name": "TestPoint",
"type": "uint16",
"sf": "TestSF"
}
p_sf = device.Point()
setattr(p_sf, "_value", 3)
points = {'TestSF': p_sf}
m = device.Model()
g = device.Group()
setattr(m, 'points', points)
setattr(g, 'points', points)
p7 = device.Point(p_def2, model=m)
setattr(p7, "static", True)
setattr(p7, "group", g)
p7.set_mb(b'\x0f\xa0', computed=True, dirty=True)
assert p7.value == 4
setattr(p_sf, "_value", 4)
p7.set_mb(b'\x0f\xa0', computed=True, dirty=True)
assert p7.value == 4
# test static false
p_sf = device.Point()
setattr(p_sf, "_value", 3)
points = {'TestSF': p_sf}
m = device.Model()
g = device.Group()
setattr(m, 'points', points)
setattr(g, 'points', points)
p8 = device.Point(p_def2, model=m)
setattr(p8, "group", g)
p8.set_mb(b'\x9c\x40', computed=True, dirty=True)
assert p8.value == 40
setattr(p_sf, "_value", 4)
p8.set_mb(b'\x9c\x40', computed=True, dirty=True)
assert p8.value == 4
def test_get_text(self, model_705_data):
m = device.Model(705, data=model_705_data)
p = m.NPt
expected_output = ' NPt 4\n'
assert p.get_text() == expected_output
class TestGroup:
def test___init__(self):
g_704 = {
"group": {
"groups": [
{
"name": "PFWInj",
"points": [
{
"name": "PF",
"sf": "PF_SF",
"type": "uint16"
},
],
"type": "sync"
},
{
"name": "PFWInjRvrt",
"points": [
{
"name": "Ext",
"type": "enum16"
}
],
"type": "sync"
},
],
"name": "DERCtlAC",
"points": [
{
"name": "ID",
"type": "uint16",
"value": 704
},
{
"name": "L",
"static": "S",
"type": "uint16"
},
{
"name": "PFWInjRvrtTms",
"type": "uint32",
},
{
"name": "PFWInjRvrtRem",
"type": "uint32",
},
{
"name": "PFWAbsEna",
"type": "enum16"
},
{
"name": "PF_SF",
"type": "sunssf"
}
],
"type": "group"
},
"id": 704
}
g = device.Group(g_704['group'])
assert g.gdef == g_704['group']
assert g.model is None
assert g.gname == 'DERCtlAC'
assert g.offset == 0
assert g.len == 10
assert len(g.points) == 6
assert len(g.groups) == 2
assert g.points_len == 8
assert g.group_class == device.Group
def test___getattr__(self):
g_704 = {
"group": {
"groups": [
{
"name": "PFWInj",
"points": [
{
"name": "PF",
"sf": "PF_SF",
"type": "uint16"
},
],
"type": "sync"
},
{
"name": "PFWInjRvrt",
"points": [
{
"name": "Ext",
"type": "enum16"
}
],
"type": "sync"
},
],
"name": "DERCtlAC",
"points": [
{
"name": "ID",
"type": "uint16",
"value": 704
},
{
"name": "L",
"static": "S",
"type": "uint16"
},
{
"name": "PFWInjRvrtTms",
"type": "uint32",
},
{
"name": "PFWInjRvrtRem",
"type": "uint32",
},
{
"name": "PFWAbsEna",
"type": "enum16"
},
{
"name": "PF_SF",
"type": "sunssf"
}
],
"type": "group"
},
"id": 704
}
g = device.Group(g_704['group'])
with pytest.raises(AttributeError) as exc:
g.qwerty
assert "Group object has no attribute qwerty" in str(exc.value)
assert g.ID
assert g.PFWAbsEna
def test__group_data(self):
gdef_705 = {
"group": {
"groups": [
{
"count": "NCrv",
"groups": [
{
"count": "NPt",
"name": "Pt",
"points": [
{
"name": "V",
"sf": "V_SF",
"type": "uint16",
},
{
"name": "Var",
"sf": "DeptRef_SF",
"type": "int16",
"units": "VarPct"
}
],
"type": "group"
}
],
"name": "Crv",
"points": [
{
"name": "ActPt",
"type": "uint16"
},
{
"name": "DeptRef",
"symbols": [
{
"name": "W_MAX_PCT",
"value": 1
},
{
"name": "VAR_MAX_PCT",
"value": 2
},
{
"name": "VAR_AVAL_PCT",
"value": 3
}
],
"type": "enum16"
},
{
"name": "Pri",
"symbols": [
{
"name": "ACTIVE",
"value": 1
},
{
"name": "REACTIVE",
"value": 2
},
{
"name": "IEEE_1547",
"value": 3
},
{
"name": "PF",
"value": 4
},
{
"name": "VENDOR",
"value": 5
}
],
"type": "enum16"
},
{
"name": "VRef",
"type": "uint16"
},
{
"name": "VRefAuto",
"symbols": [
{
"name": "DISABLED",
"value": 0
},
{
"name": "ENABLED",
"value": 1
}
],
"type": "enum16"
},
{
"name": "VRefTms",
"type": "uint16"
},
{
"name": "RspTms",
"type": "uint16"
},
{
"name": "ReadOnly",
"symbols": [
{
"name": "RW",
"value": 0
},
{
"name": "R",
"value": 1
}
],
"type": "enum16"
}
],
"type": "group"
}
],
"name": "DERVoltVar",
"points": [
{
"name": "ID",
"type": "uint16",
"value": 705
},
{
"name": "L",
"type": "uint16"
},
{
"name": "Ena",
"symbols": [
{
"name": "DISABLED",
"value": 0
},
{
"name": "ENABLED",
"value": 1
}
],
"type": "enum16"
},
{
"name": "CrvSt",
"symbols": [
{
"name": "INACTIVE",
"value": 0
},
{
"name": "ACTIVE",
"value": 1
}
],
"type": "enum16"
},
{
"name": "AdptCrvReq",
"type": "uint16"
},
{
"name": "AdptCrvRslt",
"symbols": [
{
"name": "IN_PROGRESS",
"value": 0
},
{
"name": "COMPLETED",
"value": 1
},
{
"name": "FAILED",
"value": 2
}
],
"type": "enum16"
},
{
"name": "NPt",
"type": "uint16"
},
{
"name": "NCrv",
"type": "uint16"
},
{
"name": "RvrtTms",
"type": "uint32"
},
{
"name": "RvrtRem",
"type": "uint32"
},
{
"name": "RvrtCrv",
"type": "uint16"
},
{
"name": "V_SF",
"type": "sunssf"
},
{
"name": "DeptRef_SF",
"type": "sunssf"
}
],
"type": "group"
},
"id": 705
}
gdata_705 = {
"ID": 705,
"Ena": 1,
"CrvSt": 1,
"AdptCrvReq": 0,
"AdptCrvRslt": 0,
"NPt": 4,
"NCrv": 3,
"RvrtTms": 0,
"RvrtRem": 0,
"RvrtCrv": 0,
"V_SF": -2,
"DeptRef_SF": -2,
"Crv": [
{
"ActPt": 4,
"DeptRef": 1,
"Pri": 1,
"VRef": 1,
"VRefAuto": 0,
"VRefTms": 5,
"RspTms": 6,
"ReadOnly": 1,
"Pt": [
{
"V": 9200,
"Var": 3000
},
{
"V": 9670,
"Var": 0
},
{
"V": 10300,
"Var": 0
},
{
"V": 10700,
"Var": -3000
}
]
},
{
"ActPt": 4,
"DeptRef": 1,
"Pri": 1,
"VRef": 1,
"VRefAuto": 0,
"VRefTms": 5,
"RspTms": 6,
"ReadOnly": 0,
"Pt": [
{
"V": 9300,
"Var": 3000
},
{
"V": 9570,
"Var": 0
},
{
"V": 10200,
"Var": 0
},
{
"V": 10600,
"Var": -4000
}
]
},
{
"ActPt": 4,
"DeptRef": 1,
"Pri": 1,
"VRef": 1,
"VRefAuto": 0,
"VRefTms": 5,
"RspTms": 6,
"ReadOnly": 0,
"Pt": [
{
"V": 9400,
"Var": 2000
},
{
"V": 9570,
"Var": 0
},
{
"V": 10500,
"Var": 0
},
{
"V": 10800,
"Var": -2000
}
]
}
]
}
g = device.Group()
assert g._group_data(gdata_705, 'Crv') == [{'ActPt': 4, 'DeptRef': 1, 'Pri': 1, 'VRef': 1, 'VRefAuto': 0,
'VRefTms': 5, 'RspTms': 6, 'ReadOnly': 1,
'Pt': [{'V': 9200, 'Var': 3000}, {'V': 9670, 'Var': 0},
{'V': 10300, 'Var': 0}, {'V': 10700, 'Var': -3000}]},
{'ActPt': 4, 'DeptRef': 1, 'Pri': 1, 'VRef': 1, 'VRefAuto': 0,
'VRefTms': 5, 'RspTms': 6, 'ReadOnly': 0,
'Pt': [{'V': 9300, 'Var': 3000}, {'V': 9570, 'Var': 0},
{'V': 10200, 'Var': 0}, {'V': 10600, 'Var': -4000}]},
{'ActPt': 4, 'DeptRef': 1, 'Pri': 1, 'VRef': 1, 'VRefAuto': 0,
'VRefTms': 5, 'RspTms': 6, 'ReadOnly': 0,
'Pt': [{'V': 9400, 'Var': 2000}, {'V': 9570, 'Var': 0},
{'V': 10500, 'Var': 0}, {'V': 10800, 'Var': -2000}]}]
assert g._group_data(gdata_705['Crv'], index=0) == {'ActPt': 4, 'DeptRef': 1, 'Pri': 1, 'VRef': 1,
'VRefAuto': 0, 'VRefTms': 5, 'RspTms': 6, 'ReadOnly': 1,
'Pt': [{'V': 9200, 'Var': 3000}, {'V': 9670, 'Var': 0},
{'V': 10300, 'Var': 0}, {'V': 10700, 'Var': -3000}]}
def test__get_data_group_count(self):
gdata_705 = {
"ID": 705,
"Ena": 1,
"CrvSt": 1,
"AdptCrvReq": 0,
"AdptCrvRslt": 0,
"NPt": 4,
"NCrv": 3,
"RvrtTms": 0,
"RvrtRem": 0,
"RvrtCrv": 0,
"V_SF": -2,
"DeptRef_SF": -2,
"Crv": [
{
"ActPt": 4,
"DeptRef": 1,
"Pri": 1,
"VRef": 1,
"VRefAuto": 0,
"VRefTms": 5,
"RspTms": 6,
"ReadOnly": 1,
"Pt": [
{
"V": 9200,
"Var": 3000
},
{
"V": 9670,
"Var": 0
},
{
"V": 10300,
"Var": 0
},
{
"V": 10700,
"Var": -3000
}
]
},
{
"ActPt": 4,
"DeptRef": 1,
"Pri": 1,
"VRef": 1,
"VRefAuto": 0,
"VRefTms": 5,
"RspTms": 6,
"ReadOnly": 0,
"Pt": [
{
"V": 9300,
"Var": 3000
},
{
"V": 9570,
"Var": 0
},
{
"V": 10200,
"Var": 0
},
{
"V": 10600,
"Var": -4000
}
]
},
{
"ActPt": 4,
"DeptRef": 1,
"Pri": 1,
"VRef": 1,
"VRefAuto": 0,
"VRefTms": 5,
"RspTms": 6,
"ReadOnly": 0,
"Pt": [
{
"V": 9400,
"Var": 2000
},
{
"V": 9570,
"Var": 0
},
{
"V": 10500,
"Var": 0
},
{
"V": 10800,
"Var": -2000
}
]
}
]
}
g = device.Group()
assert g._get_data_group_count(gdata_705['Crv']) == 3
def test__init_repeating_group(self):
gdef_705 = {
"group": {
"groups": [
{
"count": "NCrv",
"groups": [
{
"count": "NPt",
"name": "Pt",
"points": [
{
"name": "V",
"sf": "V_SF",
"type": "uint16",
},
{
"name": "Var",
"sf": "DeptRef_SF",
"type": "int16",
"units": "VarPct"
}
],
"type": "group"
}
],
"name": "Crv",
"points": [
{
"name": "ActPt",
"type": "uint16"
},
{
"name": "DeptRef",
"symbols": [
{
"name": "W_MAX_PCT",
"value": 1
},
{
"name": "VAR_MAX_PCT",
"value": 2
},
{
"name": "VAR_AVAL_PCT",
"value": 3
}
],
"type": "enum16"
},
{
"name": "Pri",
"symbols": [
{
"name": "ACTIVE",
"value": 1
},
{
"name": "REACTIVE",
"value": 2
},
{
"name": "IEEE_1547",
"value": 3
},
{
"name": "PF",
"value": 4
},
{
"name": "VENDOR",
"value": 5
}
],
"type": "enum16"
},
{
"name": "VRef",
"type": "uint16"
},
{
"name": "VRefAuto",
"symbols": [
{
"name": "DISABLED",
"value": 0
},
{
"name": "ENABLED",
"value": 1
}
],
"type": "enum16"
},
{
"name": "VRefTms",
"type": "uint16"
},
{
"name": "RspTms",
"type": "uint16"
},
{
"name": "ReadOnly",
"symbols": [
{
"name": "RW",
"value": 0
},
{
"name": "R",
"value": 1
}
],
"type": "enum16"
}
],
"type": "group"
}
],
"name": "DERVoltVar",
"points": [
{
"name": "ID",
"type": "uint16",
"value": 705
},
{
"name": "L",
"type": "uint16"
},
{
"name": "Ena",
"symbols": [
{
"name": "DISABLED",
"value": 0
},
{
"name": "ENABLED",
"value": 1
}
],
"type": "enum16"
},
{
"name": "CrvSt",
"symbols": [
{
"name": "INACTIVE",
"value": 0
},
{
"name": "ACTIVE",
"value": 1
}
],
"type": "enum16"
},
{
"name": "AdptCrvReq",
"type": "uint16"
},
{
"name": "AdptCrvRslt",
"symbols": [
{
"name": "IN_PROGRESS",
"value": 0
},
{
"name": "COMPLETED",
"value": 1
},
{
"name": "FAILED",
"value": 2
}
],
"type": "enum16"
},
{
"name": "NPt",
"type": "uint16"
},
{
"name": "NCrv",
"type": "uint16"
},
{
"name": "RvrtTms",
"type": "uint32"
},
{
"name": "RvrtRem",
"type": "uint32"
},
{
"name": "RvrtCrv",
"type": "uint16"
},
{
"name": "V_SF",
"type": "sunssf"
},
{
"name": "DeptRef_SF",
"type": "sunssf"
}
],
"type": "group"
},
"id": 705
}
gdata_705 = {
"ID": 705,
"Ena": 1,
"CrvSt": 1,
"AdptCrvReq": 0,
"AdptCrvRslt": 0,
"NPt": 4,
"NCrv": 3,
"RvrtTms": 0,
"RvrtRem": 0,
"RvrtCrv": 0,
"V_SF": -2,
"DeptRef_SF": -2,
"Crv": [
{
"ActPt": 4,
"DeptRef": 1,
"Pri": 1,
"VRef": 1,
"VRefAuto": 0,
"VRefTms": 5,
"RspTms": 6,
"ReadOnly": 1,
"Pt": [
{
"V": 9200,
"Var": 3000
},
{
"V": 9670,
"Var": 0
},
{
"V": 10300,
"Var": 0
},
{
"V": 10700,
"Var": -3000
}
]
},
{
"ActPt": 4,
"DeptRef": 1,
"Pri": 1,
"VRef": 1,
"VRefAuto": 0,
"VRefTms": 5,
"RspTms": 6,
"ReadOnly": 0,
"Pt": [
{
"V": 9300,
"Var": 3000
},
{
"V": 9570,
"Var": 0
},
{
"V": 10200,
"Var": 0
},
{
"V": 10600,
"Var": -4000
}
]
},
{
"ActPt": 4,
"DeptRef": 1,
"Pri": 1,
"VRef": 1,
"VRefAuto": 0,
"VRefTms": 5,
"RspTms": 6,
"ReadOnly": 0,
"Pt": [
{
"V": 9400,
"Var": 2000
},
{
"V": 9570,
"Var": 0
},
{
"V": 10500,
"Var": 0
},
{
"V": 10800,
"Var": -2000
}
]
}
]
}
m = device.Model(705, data=gdata_705)
pdef_NPt = {"name": "NPt", "type": "uint16"}
p_NPt = device.Point(pdef_NPt)
p_NPt.value = 4
pdef_NCrv = {"name": "NCrv", "type": "uint16"}
p_NCrv = device.Point(pdef_NCrv)
points = {'NPt': p_NPt, 'NCrv': p_NCrv}
setattr(m, 'points', points)
g2 = device.Group(gdef_705['group']['groups'][0], m)
with pytest.raises(device.ModelError) as exc:
g2._init_repeating_group(gdef_705['group']['groups'][0], 0, gdata_705, 0)
assert 'Count field NCrv value not initialized for group Crv' in str(exc.value)
# set value for NCrv count and reset the points attribute on model
p_NCrv.value = 3
setattr(m, 'points', points)
groups = g2._init_repeating_group(gdef_705['group']['groups'][0], 0, gdata_705, 0)
assert len(groups) == 3
assert len(groups[0].groups['Pt']) == 4
def test_get_dict(self):
gdata_705 = {
"ID": 705,
"Ena": 1,
"CrvSt": 1,
"AdptCrvReq": 0,
"AdptCrvRslt": 0,
"NPt": 4,
"NCrv": 3,
"RvrtTms": 0,
"RvrtRem": 0,
"RvrtCrv": 0,
"V_SF": -2,
"DeptRef_SF": -2,
"Crv": [
{
"ActPt": 4,
"DeptRef": 1,
"Pri": 1,
"VRef": 1,
"VRefAuto": 0,
"VRefTms": 5,
"RspTms": 6,
"ReadOnly": 1,
"Pt": [
{
"V": 9200,
"Var": 3000
},
{
"V": 9670,
"Var": 0
},
{
"V": 10300,
"Var": 0
},
{
"V": 10700,
"Var": -3000
}
]
},
{
"ActPt": 4,
"DeptRef": 1,
"Pri": 1,
"VRef": 1,
"VRefAuto": 0,
"VRefTms": 5,
"RspTms": 6,
"ReadOnly": 0,
"Pt": [
{
"V": 9300,
"Var": 3000
},
{
"V": 9570,
"Var": 0
},
{
"V": 10200,
"Var": 0
},
{
"V": 10600,
"Var": -4000
}
]
},
{
"ActPt": 4,
"DeptRef": 1,
"Pri": 1,
"VRef": 1,
"VRefAuto": 0,
"VRefTms": 5,
"RspTms": 6,
"ReadOnly": 0,
"Pt": [
{
"V": 9400,
"Var": 2000
},
{
"V": 9570,
"Var": 0
},
{
"V": 10500,
"Var": 0
},
{
"V": 10800,
"Var": -2000
}
]
}
]
}
m2 = device.Model(705, data=gdata_705)
assert m2.groups['Crv'][0].get_dict() == {'ActPt': 4, 'DeptRef': 1, 'Pri': 1, 'VRef': 1, 'VRefAuto': 0,
'VRefAutoEna': None, 'VRefAutoTms': None,
'RspTms': 6, 'ReadOnly': 1,
'Pt': [{'V': 9200, 'Var': 3000}, {'V': 9670, 'Var': 0},
{'V': 10300, 'Var': 0},
{'V': 10700, 'Var': -3000}]}
# test computed
m2.groups['Crv'][0].points['DeptRef'].sf_required = True
m2.groups['Crv'][0].points['DeptRef'].sf_value = -2
m2.groups['Crv'][0].DeptRef.cvalue = 1.16
m2.groups['Crv'][0].points['Pri'].sf_required = True
m2.groups['Crv'][0].points['Pri'].sf_value = 3
computed_dict = m2.groups['Crv'][0].get_dict(computed=True)
assert computed_dict['DeptRef'] == 1.16
assert computed_dict['Pri'] == 1000.0
def test_set_dict(self):
gdata_705 = {
"ID": 705,
"Ena": 1,
"CrvSt": 1,
"AdptCrvReq": 0,
"AdptCrvRslt": 0,
"NPt": 4,
"NCrv": 3,
"RvrtTms": 0,
"RvrtRem": 0,
"RvrtCrv": 0,
"V_SF": -2,
"DeptRef_SF": -2,
"RspTms_SF": 1,
"Crv": [
{
"ActPt": 4,
"DeptRef": 1,
"Pri": 1,
"VRef": 1,
"VRefAuto": 0,
"VRefTms": 5,
"RspTms": 6,
"ReadOnly": 1,
"Pt": [
{
"V": 9200,
"Var": 3000
},
{
"V": 9670,
"Var": 0
},
{
"V": 10300,
"Var": 0
},
{
"V": 10700,
"Var": -3000
}
]
},
{
"ActPt": 4,
"DeptRef": 1,
"Pri": 1,
"VRef": 1,
"VRefAuto": 0,
"VRefTms": 5,
"RspTms": 6,
"ReadOnly": 0,
"Pt": [
{
"V": 9300,
"Var": 3000
},
{
"V": 9570,
"Var": 0
},
{
"V": 10200,
"Var": 0
},
{
"V": 10600,
"Var": -4000
}
]
},
{
"ActPt": 4,
"DeptRef": 1,
"Pri": 1,
"VRef": 1,
"VRefAuto": 0,
"VRefTms": 5,
"RspTms": 6,
"ReadOnly": 0,
"Pt": [
{
"V": 9400,
"Var": 2000
},
{
"V": 9570,
"Var": 0
},
{
"V": 10500,
"Var": 0
},
{
"V": 10800,
"Var": -2000
}
]
}
]
}
m = device.Model(705, data=gdata_705)
assert m.groups['Crv'][0].get_dict() == {'ActPt': 4, 'DeptRef': 1, 'Pri': 1, 'VRef': 1, 'VRefAuto': 0,
'VRefAutoEna': None, 'VRefAutoTms': None,
'RspTms': 6, 'ReadOnly': 1,
'Pt': [{'V': 9200, 'Var': 3000}, {'V': 9670, 'Var': 0},
{'V': 10300, 'Var': 0},
{'V': 10700, 'Var': -3000}]}
new_dict = {'ActPt': 4, 'DeptRef': 4000, 'Pri': 5000, 'VRef': 3, 'VRefAuto': 2,
'VRefAutoEna': None, 'VRefAutoTms': None,
'RspTms': 2, 'ReadOnly': 2,
'Pt': [{'V': 111, 'Var': 111}, {'V': 123, 'Var': 1112},
{'V': 111, 'Var': 111},
{'V': 123, 'Var': -1112}]}
m.groups['Crv'][0].set_dict(new_dict, dirty=True)
assert m.groups['Crv'][0].get_dict() == new_dict
assert m.groups['Crv'][0].VRef.value == 3
assert m.groups['Crv'][0].VRef.dirty
assert m.groups['Crv'][0].Pri.dirty
m.groups['Crv'][0].points['DeptRef'].sf_required = True
m.groups['Crv'][0].points['DeptRef'].sf_value = 3
m.groups['Crv'][0].points['Pri'].sf_required = True
m.groups['Crv'][0].points['Pri'].sf_value = 3
m.groups['Crv'][0].set_dict(new_dict, computed=True)
computed_dict = m.groups['Crv'][0].get_dict()
assert computed_dict['DeptRef'] == 4.0
assert computed_dict['Pri'] == 5.0
m.groups['Crv'][0].DeptRef.sf_value = -2
float_dict = {'DeptRef': 1.16}
m.groups['Crv'][0].set_dict(float_dict, computed=True)
assert m.groups['Crv'][0].DeptRef.value == 116
assert m.groups['Crv'][0].DeptRef.cvalue == 1.16
def test_get_json(self):
gdata_705 = {
"ID": 705,
"Ena": 1,
"CrvSt": 1,
"AdptCrvReq": 0,
"AdptCrvRslt": 0,
"NPt": 4,
"NCrv": 3,
"RvrtTms": 0,
"RvrtRem": 0,
"RvrtCrv": 0,
"V_SF": -2,
"DeptRef_SF": -2,
"Crv": [
{
"ActPt": 4,
"DeptRef": 1,
"Pri": 1,
"VRef": 1,
"VRefAuto": 0,
"VRefTms": 5,
"RspTms": 6,
"ReadOnly": 1,
"Pt": [
{
"V": 9200,
"Var": 3000
},
{
"V": 9670,
"Var": 0
},
{
"V": 10300,
"Var": 0
},
{
"V": 10700,
"Var": -3000
}
]
},
{
"ActPt": 4,
"DeptRef": 1,
"Pri": 1,
"VRef": 1,
"VRefAuto": 0,
"VRefTms": 5,
"RspTms": 6,
"ReadOnly": 0,
"Pt": [
{
"V": 9300,
"Var": 3000
},
{
"V": 9570,
"Var": 0
},
{
"V": 10200,
"Var": 0
},
{
"V": 10600,
"Var": -4000
}
]
},
{
"ActPt": 4,
"DeptRef": 1,
"Pri": 1,
"VRef": 1,
"VRefAuto": 0,
"VRefTms": 5,
"RspTms": 6,
"ReadOnly": 0,
"Pt": [
{
"V": 9400,
"Var": 2000
},
{
"V": 9570,
"Var": 0
},
{
"V": 10500,
"Var": 0
},
{
"V": 10800,
"Var": -2000
}
]
}
]
}
m = device.Model(705, data=gdata_705)
assert m.groups['Crv'][0].get_json() == '''{"ActPt": 4, "DeptRef": 1, "Pri": 1, "VRef": 1,''' + \
''' "VRefAuto": 0, "VRefAutoEna": null, "VRefAutoTms": null, "RspTms": 6, "ReadOnly": 1,''' + \
''' "Pt": [{"V": 9200, "Var": 3000}, {"V": 9670, "Var": 0}, {"V": 10300, "Var": 0},''' + \
''' {"V": 10700, "Var": -3000}]}'''
# test computed
m.groups['Crv'][0].points['DeptRef'].sf_required = True
m.groups['Crv'][0].points['DeptRef'].sf_value = 3
m.groups['Crv'][0].points['Pri'].sf_required = True
m.groups['Crv'][0].points['Pri'].sf_value = 3
assert m.groups['Crv'][0].get_json(computed=True) == '''{"ActPt": 4, "DeptRef": 1000.0, "Pri": 1000.0,''' + \
''' "VRef": 0.01, "VRefAuto": 0.0, "VRefAutoEna": null, "VRefAutoTms": null, "RspTms": 6,''' + \
''' "ReadOnly": 1, "Pt": [{"V": 92.0, "Var": 30.0}, {"V": 96.7, "Var": 0.0},''' + \
''' {"V": 103.0, "Var": 0.0}, {"V": 107.0, "Var": -30.0}]}'''
def test_set_json(self):
gdata_705 = {
"ID": 705,
"Ena": 1,
"CrvSt": 1,
"AdptCrvReq": 0,
"AdptCrvRslt": 0,
"NPt": 4,
"NCrv": 3,
"RvrtTms": 0,
"RvrtRem": 0,
"RvrtCrv": 0,
"V_SF": -2,
"DeptRef_SF": -2,
"RspTms_SF": 1,
"Crv": [
{
"ActPt": 4,
"DeptRef": 1,
"Pri": 1,
"VRef": 1,
"VRefAuto": 0,
"VRefTms": 5,
"RspTms": 6,
"ReadOnly": 1,
"Pt": [
{
"V": 9200,
"Var": 3000
},
{
"V": 9670,
"Var": 0
},
{
"V": 10300,
"Var": 0
},
{
"V": 10700,
"Var": -3000
}
]
},
{
"ActPt": 4,
"DeptRef": 1,
"Pri": 1,
"VRef": 1,
"VRefAuto": 0,
"VRefTms": 5,
"RspTms": 6,
"ReadOnly": 0,
"Pt": [
{
"V": 9300,
"Var": 3000
},
{
"V": 9570,
"Var": 0
},
{
"V": 10200,
"Var": 0
},
{
"V": 10600,
"Var": -4000
}
]
},
{
"ActPt": 4,
"DeptRef": 1,
"Pri": 1,
"VRef": 1,
"VRefAuto": 0,
"VRefTms": 5,
"RspTms": 6,
"ReadOnly": 0,
"Pt": [
{
"V": 9400,
"Var": 2000
},
{
"V": 9570,
"Var": 0
},
{
"V": 10500,
"Var": 0
},
{
"V": 10800,
"Var": -2000
}
]
}
]
}
m = device.Model(705, data=gdata_705)
assert m.groups['Crv'][0].get_json() == '''{"ActPt": 4, "DeptRef": 1, "Pri": 1, "VRef": 1,''' + \
''' "VRefAuto": 0, "VRefAutoEna": null, "VRefAutoTms": null, "RspTms": 6,''' + \
''' "ReadOnly": 1, "Pt": [{"V": 9200, "Var": 3000}, {"V": 9670, "Var": 0},''' + \
''' {"V": 10300, "Var": 0}, {"V": 10700, "Var": -3000}]}'''
json_to_set = '''{"ActPt": 4, "DeptRef": 9999, "Pri": 9999, "VRef": 99, "VRefAuto": 88,''' + \
''' "VRefAutoEna": null, "VRefAutoTms": 2, "RspTms": 2, "ReadOnly": 77,''' + \
''' "Pt": [{"V": 77, "Var": 66}, {"V": 55, "Var": 44}, {"V": 33, "Var": 22},''' + \
''' {"V": 111, "Var": -2222}]}'''
m.groups['Crv'][0].set_json(json_to_set)
assert m.groups['Crv'][0].get_json() == json_to_set
assert m.groups['Crv'][0].DeptRef.value == 9999
# test computed
m.groups['Crv'][0].points['DeptRef'].sf_required = True
m.groups['Crv'][0].points['DeptRef'].sf_value = 3
m.groups['Crv'][0].points['Pri'].sf_required = True
m.groups['Crv'][0].points['Pri'].sf_value = 3
m.groups['Crv'][0].set_json(json_to_set, computed=True, dirty=True)
assert m.groups['Crv'][0].points['DeptRef'].value == 10
assert m.groups['Crv'][0].points['DeptRef'].dirty
assert m.groups['Crv'][0].points['Pri'].value == 10
assert m.groups['Crv'][0].points['Pri'].dirty
def test_get_mb(self):
gdata_705 = {
"ID": 705,
"Ena": 1,
"CrvSt": 1,
"AdptCrvReq": 0,
"AdptCrvRslt": 0,
"NPt": 4,
"NCrv": 3,
"RvrtTms": 0,
"RvrtRem": 0,
"RvrtCrv": 0,
"V_SF": -2,
"DeptRef_SF": -2,
"Crv": [
{
"ActPt": 4,
"DeptRef": 1,
"Pri": 1,
"VRef": 1,
"VRefAuto": 0,
"VRefTms": 5,
"RspTms": 6,
"ReadOnly": 1,
"Pt": [
{
"V": 9200,
"Var": 3000
},
{
"V": 9670,
"Var": 0
},
{
"V": 10300,
"Var": 0
},
{
"V": 10700,
"Var": -3000
}
]
},
{
"ActPt": 4,
"DeptRef": 1,
"Pri": 1,
"VRef": 1,
"VRefAuto": 0,
"VRefTms": 5,
"RspTms": 6,
"ReadOnly": 0,
"Pt": [
{
"V": 9300,
"Var": 3000
},
{
"V": 9570,
"Var": 0
},
{
"V": 10200,
"Var": 0
},
{
"V": 10600,
"Var": -4000
}
]
},
{
"ActPt": 4,
"DeptRef": 1,
"Pri": 1,
"VRef": 1,
"VRefAuto": 0,
"VRefTms": 5,
"RspTms": 6,
"ReadOnly": 0,
"Pt": [
{
"V": 9400,
"Var": 2000
},
{
"V": 9570,
"Var": 0
},
{
"V": 10500,
"Var": 0
},
{
"V": 10800,
"Var": -2000
}
]
}
]
}
m = device.Model(705, data=gdata_705)
assert m.groups['Crv'][0].get_mb() == b'\x00\x04\x00\x01\x00\x01\x00\x01\x00\x00\xff\xff\xff\xff\x00\x00' \
b'\x00\x06\x00\x01#\xf0\x0b\xb8%\xc6\x00\x00(<\x00\x00)\xcc\xf4H'
# test computed
m.groups['Crv'][0].points['DeptRef'].sf_required = True
m.groups['Crv'][0].points['DeptRef'].sf_value = 3
m.groups['Crv'][0].points['Pri'].sf_required = True
m.groups['Crv'][0].points['Pri'].sf_value = 3
assert m.groups['Crv'][0].get_mb(computed=True) == b'\x00\x04\x03\xe8\x03\xe8\x00\x00\x00\x00\xff\xff\xff' \
b'\xff\x00\x00\x00\x06\x00\x01\x00\\\x00\x1e\x00`\x00' \
b'\x00\x00g\x00\x00\x00k\xff\xe2'
def test_set_mb(self):
gdata_705 = {
"ID": 705,
"Ena": 1,
"CrvSt": 1,
"AdptCrvReq": 0,
"AdptCrvRslt": 0,
"NPt": 4,
"NCrv": 3,
"RvrtTms": 0,
"RvrtRem": 0,
"RvrtCrv": 0,
"V_SF": -2,
"DeptRef_SF": -2,
"Crv": [
{
"ActPt": 4,
"DeptRef": 1,
"Pri": 1,
"VRef": 1,
"VRefAuto": 0,
"VRefTms": 5,
"RspTms": 6,
"ReadOnly": 1,
"Pt": [
{
"V": 9200,
"Var": 3000
},
{
"V": 9670,
"Var": 0
},
{
"V": 10300,
"Var": 0
},
{
"V": 10700,
"Var": -3000
}
]
},
{
"ActPt": 4,
"DeptRef": 1,
"Pri": 1,
"VRef": 1,
"VRefAuto": 0,
"VRefTms": 5,
"RspTms": 6,
"ReadOnly": 0,
"Pt": [
{
"V": 9300,
"Var": 3000
},
{
"V": 9570,
"Var": 0
},
{
"V": 10200,
"Var": 0
},
{
"V": 10600,
"Var": -4000
}
]
},
{
"ActPt": 4,
"DeptRef": 1,
"Pri": 1,
"VRef": 1,
"VRefAuto": 0,
"VRefTms": 5,
"RspTms": 6,
"ReadOnly": 0,
"Pt": [
{
"V": 9400,
"Var": 2000
},
{
"V": 9570,
"Var": 0
},
{
"V": 10500,
"Var": 0
},
{
"V": 10800,
"Var": -2000
}
]
}
]
}
m = device.Model(705, data=gdata_705)
assert m.groups['Crv'][0].get_mb() == b'\x00\x04\x00\x01\x00\x01\x00\x01\x00\x00\xff\xff\xff\xff\x00\x00' \
b'\x00\x06\x00\x01#\xf0\x0b\xb8%\xc6\x00\x00(<\x00\x00)\xcc\xf4H'
bs = b'\x00\x04\x03\xe7\x03x\x03\t\x02\x9a\x02+\x01\xbc\x01M\x00\xde\x00o' \
b'\x00\xde\x01M\x01\xbc\x02+\x02\x9a\xfc\xf7\xf4H\x0b\xb8'
m.groups['Crv'][0].set_mb(bs, dirty=True)
assert m.groups['Crv'][0].get_mb() == bs
assert m.groups['Crv'][0].DeptRef.value == 999
assert m.groups['Crv'][0].DeptRef.dirty
# test computed
# set points DeptRef and Pri to 3000 w/ byte string
computed_bs = b'\x00\x04\x0b\xb8\x0b\xb8\x00\x01\x00\x00\x00\x05\x00\x06\x00\x01#\xf0\x0b\xb8%\xc6\x00\x00(<' \
b'\x00\x00)\xcc\xf4H'
m.groups['Crv'][0].points['DeptRef'].sf_required = True
m.groups['Crv'][0].points['DeptRef'].sf_value = 3
m.groups['Crv'][0].points['Pri'].sf_required = True
m.groups['Crv'][0].points['Pri'].sf_value = 3
m.groups['Crv'][0].set_mb(computed_bs, computed=True)
assert m.groups['Crv'][0].points['DeptRef'].value == 3
assert m.groups['Crv'][0].points['Pri'].value == 3
def test_get_text(self, model_705_data):
m = device.Model(705, data=model_705_data)
g = m.groups['Crv'][0]
expected_output = ''' ActPt 4\n''' + \
''' DeptRef 1\n''' + \
''' Pri 1\n''' + \
''' VRef 1 VNomPct\n''' + \
''' VRefAuto 0 VNomPct\n''' + \
''' VRefAutoEna None\n''' + \
''' VRefAutoTms None Secs\n''' + \
''' RspTms 6 Secs\n''' + \
''' ReadOnly 1\n''' + \
''' 01:V 9200 VNomPct\n''' + \
''' 01:Var 3000 DeptRef\n''' + \
''' 02:V 9670 VNomPct\n''' + \
''' 02:Var 0 DeptRef\n''' + \
''' 03:V 10300 VNomPct\n''' + \
''' 03:Var 0 DeptRef\n''' + \
''' 04:V 10700 VNomPct\n''' + \
''' 04:Var 3000 DeptRef\n'''
assert g.get_text() == expected_output
class TestModel:
def test__init__(self):
m = device.Model(704)
assert m.model_id == 704
assert m.model_addr == 0
assert m.model_len == 0
assert m.model_def['id'] == 704
assert m.error_info == ''
assert m.gdef['name'] == 'DERCtlAC'
assert m.mid is None
assert m.device is None
assert m.model == m
m2 = device.Model('abc')
assert m2.error_info == 'Invalid model id: abc\n'
gdata_705 = {
"ID": 705,
"Ena": 1,
"CrvSt": 1,
"AdptCrvReq": 0,
"AdptCrvRslt": 0,
"NPt": 4,
"NCrv": 3,
"RvrtTms": 0,
"RvrtRem": 0,
"RvrtCrv": 0,
"V_SF": -2,
"DeptRef_SF": -2,
"Crv": [
{
"ActPt": 4,
"DeptRef": 1,
"Pri": 1,
"VRef": 1,
"VRefAuto": 0,
"VRefTms": 5,
"RspTms": 6,
"ReadOnly": 1,
"Pt": [
{
"V": 9200,
"Var": 3000
},
{
"V": 9670,
"Var": 0
},
{
"V": 10300,
"Var": 0
},
{
"V": 10700,
"Var": -3000
}
]
},
{
"ActPt": 4,
"DeptRef": 1,
"Pri": 1,
"VRef": 1,
"VRefAuto": 0,
"VRefTms": 5,
"RspTms": 6,
"ReadOnly": 0,
"Pt": [
{
"V": 9300,
"Var": 3000
},
{
"V": 9570,
"Var": 0
},
{
"V": 10200,
"Var": 0
},
{
"V": 10600,
"Var": -4000
}
]
},
{
"ActPt": 4,
"DeptRef": 1,
"Pri": 1,
"VRef": 1,
"VRefAuto": 0,
"VRefTms": 5,
"RspTms": 6,
"ReadOnly": 0,
"Pt": [
{
"V": 9400,
"Var": 2000
},
{
"V": 9570,
"Var": 0
},
{
"V": 10500,
"Var": 0
},
{
"V": 10800,
"Var": -2000
}
]
}
]
}
# test repeating group model
m2 = device.Model(705, data=gdata_705)
assert m2.model_id == 705
assert m2.model_addr == 0
assert m2.model_len == 0
assert m2.model_def['id'] == 705
assert m2.error_info == ''
assert m2.gdef['name'] == 'DERVoltVar'
assert m2.mid is None
assert m2.device is None
def test_model_1():
mdata = {
"ID": 1,
"L": 68,
"Mn": "Test manuf",
"Md": "Test model",
"Opt": "Test options",
"Vr": "Test version",
"SN": "Test serial num",
"DA": 12,
"Pad": 0
}
m = device.Model(1, data=mdata)
def test__error():
m = device.Model(704)
m.add_error('test error')
assert m.error_info == 'test error\n'
def test_get_text(model_705_data):
m = device.Model(705, data=model_705_data)
expected_output = ''' ID 705\n''' + \
''' L 67\n''' + \
''' Ena 1\n''' + \
''' AdptCrvReq 0\n''' + \
''' AdptCrvRslt 0\n''' + \
''' NPt 4\n''' + \
''' NCrv 3\n''' + \
''' RvrtTms 0 Secs\n''' + \
''' RvrtRem 0 Secs\n''' + \
''' RvrtCrv 0\n''' + \
''' V_SF -2\n''' + \
''' DeptRef_SF -2\n''' + \
''' RspTms_SF None\n''' + \
''' 01:ActPt 4\n''' + \
''' 01:DeptRef 1\n''' + \
''' 01:Pri 1\n''' + \
''' 01:VRef 1 VNomPct\n''' + \
''' 01:VRefAuto 0 VNomPct\n''' + \
''' 01:VRefAutoEna None\n''' + \
''' 01:VRefAutoTms None Secs\n''' + \
''' 01:RspTms 6 Secs\n''' + \
''' 01:ReadOnly 1\n''' + \
'''01:01:V 9200 VNomPct\n''' + \
'''01:01:Var 3000 DeptRef\n''' + \
'''01:02:V 9670 VNomPct\n''' + \
'''01:02:Var 0 DeptRef\n''' + \
'''01:03:V 10300 VNomPct\n''' + \
'''01:03:Var 0 DeptRef\n''' + \
'''01:04:V 10700 VNomPct\n''' + \
'''01:04:Var 3000 DeptRef\n''' + \
''' 02:ActPt 4\n''' + \
''' 02:DeptRef 1\n''' + \
''' 02:Pri 1\n''' + \
''' 02:VRef 1 VNomPct\n''' + \
''' 02:VRefAuto 0 VNomPct\n''' + \
''' 02:VRefAutoEna None\n''' + \
''' 02:VRefAutoTms None Secs\n''' + \
''' 02:RspTms 6 Secs\n''' + \
''' 02:ReadOnly 0\n''' + \
'''02:01:V 9300 VNomPct\n''' + \
'''02:01:Var 3000 DeptRef\n''' + \
'''02:02:V 9570 VNomPct\n''' + \
'''02:02:Var 0 DeptRef\n''' + \
'''02:03:V 10200 VNomPct\n''' + \
'''02:03:Var 0 DeptRef\n''' + \
'''02:04:V 10600 VNomPct\n''' + \
'''02:04:Var 4000 DeptRef\n''' + \
''' 03:ActPt 4\n''' + \
''' 03:DeptRef 1\n''' + \
''' 03:Pri 1\n''' + \
''' 03:VRef 1 VNomPct\n''' + \
''' 03:VRefAuto 0 VNomPct\n''' + \
''' 03:VRefAutoEna None\n''' + \
''' 03:VRefAutoTms None Secs\n''' + \
''' 03:RspTms 6 Secs\n''' + \
''' 03:ReadOnly 0\n''' + \
'''03:01:V 9400 VNomPct\n''' + \
'''03:01:Var 2000 DeptRef\n''' + \
'''03:02:V 9570 VNomPct\n''' + \
'''03:02:Var 0 DeptRef\n''' + \
'''03:03:V 10500 VNomPct\n''' + \
'''03:03:Var 0 DeptRef\n''' + \
'''03:04:V 10800 VNomPct\n''' + \
'''03:04:Var 2000 DeptRef\n'''
assert expected_output == m.get_text()
class TestDevice:
def test__init__(self):
d = device.Device()
assert d.name is None
assert d.did is None
assert d.models == {}
assert d.model_list == []
assert d.model_class == device.Model
def test__get_attr__(self):
d = device.Device()
m = device.Model()
setattr(m, 'model_id', 'mid_test')
setattr(m, 'gname', 'group_test')
d.add_model(m)
assert d.mid_test
with pytest.raises(AttributeError) as exc:
d.foo
assert "\'Device\' object has no attribute \'foo\'" in str(exc.value)
def test_scan(self):
pass
def test_add_model(self):
d = device.Device()
m = device.Model()
setattr(m, 'model_id', 'mid_test')
setattr(m, 'gname', 'group_test')
d.add_model(m)
assert d.models['mid_test']
assert d.models['group_test']
assert m.device == d
def test_get_dict(self):
d = device.Device()
gdata_705 = {
"ID": 705,
"Ena": 1,
"CrvSt": 1,
"AdptCrvReq": 0,
"AdptCrvRslt": 0,
"NPt": 4,
"NCrv": 3,
"RvrtTms": 0,
"RvrtRem": 0,
"RvrtCrv": 0,
"V_SF": -2,
"DeptRef_SF": -2,
"Crv": [
{
"ActPt": 4,
"DeptRef": 1,
"Pri": 1,
"VRef": 1,
"VRefAuto": 0,
"VRefTms": 5,
"RspTms": 6,
"ReadOnly": 1,
"Pt": [
{
"V": 9200,
"Var": 3000
},
{
"V": 9670,
"Var": 0
},
{
"V": 10300,
"Var": 0
},
{
"V": 10700,
"Var": -3000
}
]
},
{
"ActPt": 4,
"DeptRef": 1,
"Pri": 1,
"VRef": 1,
"VRefAuto": 0,
"VRefTms": 5,
"RspTms": 6,
"ReadOnly": 0,
"Pt": [
{
"V": 9300,
"Var": 3000
},
{
"V": 9570,
"Var": 0
},
{
"V": 10200,
"Var": 0
},
{
"V": 10600,
"Var": -4000
}
]
},
{
"ActPt": 4,
"DeptRef": 1,
"Pri": 1,
"VRef": 1,
"VRefAuto": 0,
"VRefTms": 5,
"RspTms": 6,
"ReadOnly": 0,
"Pt": [
{
"V": 9400,
"Var": 2000
},
{
"V": 9570,
"Var": 0
},
{
"V": 10500,
"Var": 0
},
{
"V": 10800,
"Var": -2000
}
]
}
]
}
m = device.Model(705, data=gdata_705)
d.add_model(m)
assert d.get_dict() == {'name': None, 'did': None, 'models': [
{'ID': 705, 'L': 67, 'Ena': 1, 'AdptCrvReq': 0, 'AdptCrvRslt': 0, 'NPt': 4, 'NCrv': 3, 'RvrtTms': 0,
'RvrtRem': 0, 'RvrtCrv': 0, 'V_SF': -2, 'DeptRef_SF': -2, 'RspTms_SF': None, 'Crv': [
{'ActPt': 4, 'DeptRef': 1, 'Pri': 1, 'VRef': 1, 'VRefAuto': 0, 'VRefAutoEna': None, 'VRefAutoTms': None,
'RspTms': 6, 'ReadOnly': 1,
'Pt': [{'V': 9200, 'Var': 3000}, {'V': 9670, 'Var': 0}, {'V': 10300, 'Var': 0},
{'V': 10700, 'Var': -3000}]},
{'ActPt': 4, 'DeptRef': 1, 'Pri': 1, 'VRef': 1, 'VRefAuto': 0, 'VRefAutoEna': None, 'VRefAutoTms': None,
'RspTms': 6, 'ReadOnly': 0,
'Pt': [{'V': 9300, 'Var': 3000}, {'V': 9570, 'Var': 0}, {'V': 10200, 'Var': 0},
{'V': 10600, 'Var': -4000}]},
{'ActPt': 4, 'DeptRef': 1, 'Pri': 1, 'VRef': 1, 'VRefAuto': 0, 'VRefAutoEna': None, 'VRefAutoTms': None,
'RspTms': 6, 'ReadOnly': 0,
'Pt': [{'V': 9400, 'Var': 2000}, {'V': 9570, 'Var': 0}, {'V': 10500, 'Var': 0},
{'V': 10800, 'Var': -2000}]}], 'mid': None, 'error': '', 'model_id': 705}]}
# computed
m.groups['Crv'][0].points['DeptRef'].sf_required = True
m.groups['Crv'][0].points['DeptRef'].sf_value = 3
m.groups['Crv'][0].points['Pri'].sf_required = True
m.groups['Crv'][0].points['Pri'].sf_value = 3
assert d.get_dict(computed=True) == {'name': None, 'did': None, 'models': [
{'ID': 705, 'L': 67, 'Ena': 1, 'AdptCrvReq': 0, 'AdptCrvRslt': 0, 'NPt': 4, 'NCrv': 3, 'RvrtTms': 0,
'RvrtRem': 0, 'RvrtCrv': 0, 'V_SF': -2, 'DeptRef_SF': -2, 'RspTms_SF': None, 'Crv': [
{'ActPt': 4, 'DeptRef': 1000.0, 'Pri': 1000.0, 'VRef': 0.01, 'VRefAuto': 0.0, 'VRefAutoEna': None,
'VRefAutoTms': None, 'RspTms': 6, 'ReadOnly': 1,
'Pt': [{'V': 92.0, 'Var': 30.0}, {'V': 96.7, 'Var': 0.0}, {'V': 103.0, 'Var': 0.0},
{'V': 107.0, 'Var': -30.0}]},
{'ActPt': 4, 'DeptRef': 1, 'Pri': 1, 'VRef': 0.01, 'VRefAuto': 0.0, 'VRefAutoEna': None,
'VRefAutoTms': None, 'RspTms': 6, 'ReadOnly': 0,
'Pt': [{'V': 93.0, 'Var': 30.0}, {'V': 95.7, 'Var': 0.0}, {'V': 102.0, 'Var': 0.0},
{'V': 106.0, 'Var': -40.0}]},
{'ActPt': 4, 'DeptRef': 1, 'Pri': 1, 'VRef': 0.01, 'VRefAuto': 0.0, 'VRefAutoEna': None,
'VRefAutoTms': None, 'RspTms': 6, 'ReadOnly': 0,
'Pt': [{'V': 94.0, 'Var': 20.0}, {'V': 95.7, 'Var': 0.0}, {'V': 105.0, 'Var': 0.0},
{'V': 108.0, 'Var': -20.0}]}], 'mid': None, 'error': '', 'model_id': 705}]}
def test_get_json(self):
d = device.Device()
gdata_705 = {
"ID": 705,
"Ena": 1,
"CrvSt": 1,
"AdptCrvReq": 0,
"AdptCrvRslt": 0,
"NPt": 4,
"NCrv": 3,
"RvrtTms": 0,
"RvrtRem": 0,
"RvrtCrv": 0,
"V_SF": -2,
"DeptRef_SF": -2,
"Crv": [
{
"ActPt": 4,
"DeptRef": 1,
"Pri": 1,
"VRef": 1,
"VRefAuto": 0,
"VRefTms": 5,
"RspTms": 6,
"ReadOnly": 1,
"Pt": [
{
"V": 9200,
"Var": 3000
},
{
"V": 9670,
"Var": 0
},
{
"V": 10300,
"Var": 0
},
{
"V": 10700,
"Var": -3000
}
]
},
{
"ActPt": 4,
"DeptRef": 1,
"Pri": 1,
"VRef": 1,
"VRefAuto": 0,
"VRefTms": 5,
"RspTms": 6,
"ReadOnly": 0,
"Pt": [
{
"V": 9300,
"Var": 3000
},
{
"V": 9570,
"Var": 0
},
{
"V": 10200,
"Var": 0
},
{
"V": 10600,
"Var": -4000
}
]
},
{
"ActPt": 4,
"DeptRef": 1,
"Pri": 1,
"VRef": 1,
"VRefAuto": 0,
"VRefTms": 5,
"RspTms": 6,
"ReadOnly": 0,
"Pt": [
{
"V": 9400,
"Var": 2000
},
{
"V": 9570,
"Var": 0
},
{
"V": 10500,
"Var": 0
},
{
"V": 10800,
"Var": -2000
}
]
}
]
}
m = device.Model(705, data=gdata_705)
d.add_model(m)
assert d.get_json() == '''{"name": null, "did": null, "models": [{"ID": 705, "L": 67, "Ena": 1,''' + \
''' "AdptCrvReq": 0, "AdptCrvRslt": 0, "NPt": 4, "NCrv": 3, "RvrtTms": 0, "RvrtRem": 0,''' + \
''' "RvrtCrv": 0, "V_SF": -2, "DeptRef_SF": -2, "RspTms_SF": null, "Crv": [{"ActPt": 4,''' + \
''' "DeptRef": 1, "Pri": 1, "VRef": 1, "VRefAuto": 0, "VRefAutoEna": null, "VRefAutoTms": null,''' + \
''' "RspTms": 6, "ReadOnly": 1, "Pt": [{"V": 9200, "Var": 3000}, {"V": 9670, "Var": 0},''' + \
''' {"V": 10300, "Var": 0}, {"V": 10700, "Var": -3000}]}, {"ActPt": 4, "DeptRef": 1,''' + \
''' "Pri": 1, "VRef": 1, "VRefAuto": 0, "VRefAutoEna": null, "VRefAutoTms": null,''' + \
''' "RspTms": 6, "ReadOnly": 0, "Pt": [{"V": 9300, "Var": 3000}, {"V": 9570, "Var": 0},''' + \
''' {"V": 10200, "Var": 0}, {"V": 10600, "Var": -4000}]}, {"ActPt": 4, "DeptRef": 1,''' + \
''' "Pri": 1, "VRef": 1, "VRefAuto": 0, "VRefAutoEna": null, "VRefAutoTms": null,''' + \
''' "RspTms": 6, "ReadOnly": 0, "Pt": [{"V": 9400, "Var": 2000}, {"V": 9570, "Var": 0},''' + \
''' {"V": 10500, "Var": 0}, {"V": 10800, "Var": -2000}]}], "mid": null, "error": "",''' + \
''' "model_id": 705}]}'''
# computed
m.groups['Crv'][0].points['DeptRef'].sf_required = True
m.groups['Crv'][0].points['DeptRef'].sf_value = 3
m.groups['Crv'][0].points['Pri'].sf_required = True
m.groups['Crv'][0].points['Pri'].sf_value = 3
assert d.get_json(computed=True) == '''{"name": null, "did": null, "models":''' + \
''' [{"ID": 705, "L": 67, "Ena": 1, "AdptCrvReq": 0, "AdptCrvRslt": 0,''' + \
''' "NPt": 4, "NCrv": 3, "RvrtTms": 0, "RvrtRem": 0, "RvrtCrv": 0, "V_SF": -2,''' + \
''' "DeptRef_SF": -2, "RspTms_SF": null, "Crv": [{"ActPt": 4, "DeptRef": 1000.0,''' + \
''' "Pri": 1000.0, "VRef": 0.01, "VRefAuto": 0.0, "VRefAutoEna": null,''' + \
''' "VRefAutoTms": null, "RspTms": 6, "ReadOnly": 1, "Pt": [{"V": 92.0, "Var": 30.0},''' + \
''' {"V": 96.7, "Var": 0.0}, {"V": 103.0, "Var": 0.0}, {"V": 107.0, "Var": -30.0}]},''' + \
''' {"ActPt": 4, "DeptRef": 1, "Pri": 1, "VRef": 0.01, "VRefAuto": 0.0,''' + \
''' "VRefAutoEna": null, "VRefAutoTms": null, "RspTms": 6, "ReadOnly": 0,''' + \
''' "Pt": [{"V": 93.0, "Var": 30.0}, {"V": 95.7, "Var": 0.0}, {"V": 102.0, "Var": 0.0},''' + \
''' {"V": 106.0, "Var": -40.0}]}, {"ActPt": 4, "DeptRef": 1, "Pri": 1, "VRef": 0.01,''' + \
''' "VRefAuto": 0.0, "VRefAutoEna": null, "VRefAutoTms": null, "RspTms": 6, "ReadOnly": 0,''' + \
''' "Pt": [{"V": 94.0, "Var": 20.0}, {"V": 95.7, "Var": 0.0}, {"V": 105.0, "Var": 0.0},''' + \
''' {"V": 108.0, "Var": -20.0}]}], "mid": null, "error": "", "model_id": 705}]}'''
def test_get_mb(self):
d = device.Device()
gdata_705 = {
"ID": 705,
"Ena": 1,
"CrvSt": 1,
"AdptCrvReq": 0,
"AdptCrvRslt": 0,
"NPt": 4,
"NCrv": 3,
"RvrtTms": 0,
"RvrtRem": 0,
"RvrtCrv": 0,
"V_SF": -2,
"DeptRef_SF": -2,
"Crv": [
{
"ActPt": 4,
"DeptRef": 1,
"Pri": 1,
"VRef": 1,
"VRefAuto": 0,
"VRefTms": 5,
"RspTms": 6,
"ReadOnly": 1,
"Pt": [
{
"V": 9200,
"Var": 3000
},
{
"V": 9670,
"Var": 0
},
{
"V": 10300,
"Var": 0
},
{
"V": 10700,
"Var": 3000
}
]
},
{
"ActPt": 4,
"DeptRef": 1,
"Pri": 1,
"VRef": 1,
"VRefAuto": 0,
"VRefTms": 5,
"RspTms": 6,
"ReadOnly": 0,
"Pt": [
{
"V": 9300,
"Var": 3000
},
{
"V": 9570,
"Var": 0
},
{
"V": 10200,
"Var": 0
},
{
"V": 10600,
"Var": 4000
}
]
},
{
"ActPt": 4,
"DeptRef": 1,
"Pri": 1,
"VRef": 1,
"VRefAuto": 0,
"VRefTms": 5,
"RspTms": 6,
"ReadOnly": 0,
"Pt": [
{
"V": 9400,
"Var": 2000
},
{
"V": 9570,
"Var": 0
},
{
"V": 10500,
"Var": 0
},
{
"V": 10800,
"Var": 2000
}
]
}
]
}
m = device.Model(705, data=gdata_705)
d.add_model(m)
assert d.get_mb() == b"\x02\xc1\x00C\x00\x01\x00\x00\x00\x00\x00\x04\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00" \
b"\x00\x00\xff\xfe\xff\xfe\x80\x00\x00\x04\x00\x01\x00\x01\x00\x01\x00\x00\xff\xff\xff" \
b"\xff\x00\x00\x00\x06\x00\x01#\xf0\x0b\xb8%\xc6\x00\x00(<\x00\x00)\xcc\x0b\xb8\x00\x04" \
b"\x00\x01\x00\x01\x00\x01\x00\x00\xff\xff\xff\xff\x00\x00\x00\x06\x00\x00$T\x0b\xb8%b" \
b"\x00\x00'\xd8\x00\x00)h\x0f\xa0\x00\x04\x00\x01\x00\x01\x00\x01\x00\x00\xff\xff\xff" \
b"\xff\x00\x00\x00\x06\x00\x00$\xb8\x07\xd0%b\x00\x00)\x04\x00\x00*0\x07\xd0"
# computed
m.groups['Crv'][0].points['DeptRef'].sf_required = True
m.groups['Crv'][0].points['DeptRef'].sf_value = 3
m.groups['Crv'][0].points['Pri'].sf_required = True
m.groups['Crv'][0].points['Pri'].sf_value = 3
assert d.get_mb(computed=True) == b'\x02\xc1\x00C\x00\x01\x00\x00\x00\x00\x00\x04\x00\x03\x00\x00\x00\x00\x00' \
b'\x00\x00\x00\x00\x00\xff\xfe\xff\xfe\x80\x00\x00\x04\x03\xe8\x03\xe8\x00' \
b'\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x06\x00\x01\x00\\\x00\x1e\x00`' \
b'\x00\x00\x00g\x00\x00\x00k\x00\x1e\x00\x04\x00\x01\x00\x01\x00\x00\x00' \
b'\x00\xff\xff\xff\xff\x00\x00\x00\x06\x00\x00\x00]\x00\x1e\x00_\x00\x00' \
b'\x00f\x00\x00\x00j\x00(\x00\x04\x00\x01\x00\x01\x00\x00\x00\x00\xff\xff' \
b'\xff\xff\x00\x00\x00\x06\x00\x00\x00^\x00\x14\x00_\x00\x00\x00i\x00\x00' \
b'\x00l\x00\x14'
def test_set_mb(self):
d = device.Device()
gdata_705 = {
"ID": 705,
"Ena": 1,
"CrvSt": 1,
"AdptCrvReq": 0,
"AdptCrvRslt": 0,
"NPt": 4,
"NCrv": 3,
"RvrtTms": 0,
"RvrtRem": 0,
"RvrtCrv": 0,
"V_SF": -2,
"DeptRef_SF": -2,
"Crv": [
{
"ActPt": 4,
"DeptRef": 1,
"Pri": 1,
"VRef": 1,
"VRefAuto": 0,
"VRefTms": 5,
"RspTms": 6,
"ReadOnly": 1,
"Pt": [
{
"V": 9200,
"Var": 3000
},
{
"V": 9670,
"Var": 0
},
{
"V": 10300,
"Var": 0
},
{
"V": 10700,
"Var": 3000
}
]
},
{
"ActPt": 4,
"DeptRef": 1,
"Pri": 1,
"VRef": 1,
"VRefAuto": 0,
"VRefTms": 5,
"RspTms": 6,
"ReadOnly": 0,
"Pt": [
{
"V": 9300,
"Var": 3000
},
{
"V": 9570,
"Var": 0
},
{
"V": 10200,
"Var": 0
},
{
"V": 10600,
"Var": 4000
}
]
},
{
"ActPt": 4,
"DeptRef": 1,
"Pri": 1,
"VRef": 1,
"VRefAuto": 0,
"VRefTms": 5,
"RspTms": 6,
"ReadOnly": 0,
"Pt": [
{
"V": 9400,
"Var": 2000
},
{
"V": 9570,
"Var": 0
},
{
"V": 10500,
"Var": 0
},
{
"V": 10800,
"Var": 2000
}
]
}
]
}
m = device.Model(705, data=gdata_705)
d.add_model(m)
assert d.get_mb() == b"\x02\xc1\x00C\x00\x01\x00\x00\x00\x00\x00\x04\x00\x03\x00\x00\x00\x00\x00\x00\x00" \
b"\x00\x00\x00\xff\xfe\xff\xfe\x80\x00\x00\x04\x00\x01\x00\x01\x00\x01\x00\x00\xff" \
b"\xff\xff\xff\x00\x00\x00\x06\x00\x01#\xf0\x0b\xb8%\xc6\x00\x00(<\x00\x00)\xcc\x0b" \
b"\xb8\x00\x04\x00\x01\x00\x01\x00\x01\x00\x00\xff\xff\xff\xff\x00\x00\x00\x06\x00" \
b"\x00$T\x0b\xb8%b\x00\x00'\xd8\x00\x00)h\x0f\xa0\x00\x04\x00\x01\x00\x01\x00\x01\x00" \
b"\x00\xff\xff\xff\xff\x00\x00\x00\x06\x00\x00$\xb8\x07\xd0%b\x00\x00)\x04\x00\x00*0" \
b"\x07\xd0"
# DeptRef and Pri set to 3000 in byte string
bs = b"\x02\xc1\x00?\x00\x01\x00\x01\x00\x00\x00\x00\x00\x04\x00\x03\x00\x00\x00\x00\x00\x00" \
b"\x00\x00\x00\x00\xff\xfe\xff\xfe\x00\x04\x0b\xb8\x0b\xb8\x00\x01\x00\x00\x00\x05\x00" \
b"\x06\x00\x01#\xf0\x0b\xb8%\xc6\x00\x00(<\x00\x00)\xcc\xf4H\x00\x04\x00\x01\x00\x01\x00" \
b"\x01\x00\x00\x00\x05\x00\x06\x00\x00$T\x0b\xb8%b\x00\x00'\xd8\x00\x00)h\xf0`\x00\x04" \
b"\x00\x01\x00\x01\x00\x01\x00\x00\x00\x05\x00\x06\x00\x00$\xb8\x07\xd0%b\x00\x00)\x04\x00\x00*0\xf80"
d.set_mb(bs, dirty=True)
assert m.groups['Crv'][0].DeptRef.value == 3000
assert m.groups['Crv'][0].DeptRef.dirty
assert m.groups['Crv'][0].Pri.value == 3000
assert m.groups['Crv'][0].Pri.dirty
# computed
m.groups['Crv'][0].points['DeptRef'].sf_required = True
m.groups['Crv'][0].points['DeptRef'].sf_value = 3
m.groups['Crv'][0].points['Pri'].sf_required = True
m.groups['Crv'][0].points['Pri'].sf_value = 3
d.set_mb(bs, computed=True, dirty=False)
assert m.groups['Crv'][0].DeptRef.value == 3
assert not m.groups['Crv'][0].DeptRef.dirty
assert m.groups['Crv'][0].Pri.value == 3
assert not m.groups['Crv'][0].Pri.dirty
def test_find_mid(self):
d = device.Device()
m = device.Model()
setattr(m, 'model_id', 'mid_test')
setattr(m, 'gname', 'group_test')
setattr(m, 'mid', 'mid_test')
d.add_model(m)
assert d.find_mid('mid_test') == m
def test_get_text(self, model_705_data):
d = device.Device()
m = device.Model(705, data=model_705_data)
d.add_model(m)
get_text_expected_output = '''Model: DERVoltVar (705)\n\n''' + \
''' ID 705\n''' + \
''' L 67\n''' + \
''' Ena 1\n''' + \
''' AdptCrvReq 0\n''' + \
''' AdptCrvRslt 0\n''' + \
''' NPt 4\n''' + \
''' NCrv 3\n''' + \
''' RvrtTms 0 Secs\n''' + \
''' RvrtRem 0 Secs\n''' + \
''' RvrtCrv 0\n''' + \
''' V_SF -2\n''' + \
''' DeptRef_SF -2\n''' + \
''' RspTms_SF None\n''' + \
''' 01:ActPt 4\n''' + \
''' 01:DeptRef 1\n''' + \
''' 01:Pri 1\n''' + \
''' 01:VRef 1 VNomPct\n''' + \
''' 01:VRefAuto 0 VNomPct\n''' + \
''' 01:VRefAutoEna None\n''' + \
''' 01:VRefAutoTms None Secs\n''' + \
''' 01:RspTms 6 Secs\n''' + \
''' 01:ReadOnly 1\n''' + \
'''01:01:V 9200 VNomPct\n''' + \
'''01:01:Var 3000 DeptRef\n''' + \
'''01:02:V 9670 VNomPct\n''' + \
'''01:02:Var 0 DeptRef\n''' + \
'''01:03:V 10300 VNomPct\n''' + \
'''01:03:Var 0 DeptRef\n''' + \
'''01:04:V 10700 VNomPct\n''' + \
'''01:04:Var 3000 DeptRef\n''' + \
''' 02:ActPt 4\n''' + \
''' 02:DeptRef 1\n''' + \
''' 02:Pri 1\n''' + \
''' 02:VRef 1 VNomPct\n''' + \
''' 02:VRefAuto 0 VNomPct\n''' + \
''' 02:VRefAutoEna None\n''' + \
''' 02:VRefAutoTms None Secs\n''' + \
''' 02:RspTms 6 Secs\n''' + \
''' 02:ReadOnly 0\n''' + \
'''02:01:V 9300 VNomPct\n''' + \
'''02:01:Var 3000 DeptRef\n''' + \
'''02:02:V 9570 VNomPct\n''' + \
'''02:02:Var 0 DeptRef\n''' + \
'''02:03:V 10200 VNomPct\n''' + \
'''02:03:Var 0 DeptRef\n''' + \
'''02:04:V 10600 VNomPct\n''' + \
'''02:04:Var 4000 DeptRef\n''' + \
''' 03:ActPt 4\n''' + \
''' 03:DeptRef 1\n''' + \
''' 03:Pri 1\n''' + \
''' 03:VRef 1 VNomPct\n''' + \
''' 03:VRefAuto 0 VNomPct\n''' + \
''' 03:VRefAutoEna None\n''' + \
''' 03:VRefAutoTms None Secs\n''' + \
''' 03:RspTms 6 Secs\n''' + \
''' 03:ReadOnly 0\n''' + \
'''03:01:V 9400 VNomPct\n''' + \
'''03:01:Var 2000 DeptRef\n''' + \
'''03:02:V 9570 VNomPct\n''' + \
'''03:02:Var 0 DeptRef\n''' + \
'''03:03:V 10500 VNomPct\n''' + \
'''03:03:Var 0 DeptRef\n''' + \
'''03:04:V 10800 VNomPct\n''' + \
'''03:04:Var 2000 DeptRef\n'''
get_text_output = d.get_text()
# dont compare timestamps
assert get_text_output[get_text_output.index('Model'):] == get_text_expected_output