easycoder 251215.2__py2.py3-none-any.whl → 260111.1__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- easycoder/__init__.py +4 -3
- easycoder/debugger/ec_dbg_value_display copy.py +1 -1
- easycoder/debugger/ec_dbg_value_display.py +12 -11
- easycoder/debugger/ec_dbg_watchlist.py +146 -12
- easycoder/debugger/ec_debug.py +85 -8
- easycoder/ec_classes.py +228 -25
- easycoder/ec_compiler.py +29 -8
- easycoder/ec_core.py +364 -242
- easycoder/ec_gclasses.py +20 -9
- easycoder/ec_graphics.py +42 -26
- easycoder/ec_handler.py +4 -3
- easycoder/ec_mqtt.py +248 -0
- easycoder/ec_program.py +63 -28
- easycoder/ec_psutil.py +1 -1
- easycoder/ec_value.py +57 -36
- easycoder/pre/README.md +3 -0
- easycoder/pre/__init__.py +17 -0
- easycoder/pre/debugger/__init__.py +5 -0
- easycoder/pre/debugger/ec_dbg_value_display copy.py +195 -0
- easycoder/pre/debugger/ec_dbg_value_display.py +24 -0
- easycoder/pre/debugger/ec_dbg_watch_list copy.py +219 -0
- easycoder/pre/debugger/ec_dbg_watchlist.py +293 -0
- easycoder/pre/debugger/ec_debug.py +1014 -0
- easycoder/pre/ec_border.py +67 -0
- easycoder/pre/ec_classes.py +470 -0
- easycoder/pre/ec_compiler.py +291 -0
- easycoder/pre/ec_condition.py +27 -0
- easycoder/pre/ec_core.py +2772 -0
- easycoder/pre/ec_gclasses.py +230 -0
- easycoder/pre/ec_graphics.py +1682 -0
- easycoder/pre/ec_handler.py +79 -0
- easycoder/pre/ec_keyboard.py +439 -0
- easycoder/pre/ec_program.py +557 -0
- easycoder/pre/ec_psutil.py +48 -0
- easycoder/pre/ec_timestamp.py +11 -0
- easycoder/pre/ec_value.py +124 -0
- easycoder/pre/icons/close.png +0 -0
- easycoder/pre/icons/exit.png +0 -0
- easycoder/pre/icons/run.png +0 -0
- easycoder/pre/icons/step.png +0 -0
- easycoder/pre/icons/stop.png +0 -0
- easycoder/pre/icons/tick.png +0 -0
- {easycoder-251215.2.dist-info → easycoder-260111.1.dist-info}/METADATA +1 -1
- easycoder-260111.1.dist-info/RECORD +59 -0
- easycoder-251215.2.dist-info/RECORD +0 -31
- {easycoder-251215.2.dist-info → easycoder-260111.1.dist-info}/WHEEL +0 -0
- {easycoder-251215.2.dist-info → easycoder-260111.1.dist-info}/entry_points.txt +0 -0
- {easycoder-251215.2.dist-info → easycoder-260111.1.dist-info}/licenses/LICENSE +0 -0
easycoder/ec_gclasses.py
CHANGED
|
@@ -112,6 +112,12 @@ class ECLineInput(ECTextWidget):
|
|
|
112
112
|
def hasRuntimeValue(self):
|
|
113
113
|
return True
|
|
114
114
|
|
|
115
|
+
# Set the text of the widget
|
|
116
|
+
def setText(self, text):
|
|
117
|
+
v = self.getValue()
|
|
118
|
+
if v is None: return
|
|
119
|
+
v.getContent().setText(str(text)) # type: ignore
|
|
120
|
+
|
|
115
121
|
# Get the text of the widget
|
|
116
122
|
def getText(self):
|
|
117
123
|
return self.getValue().getContent().text() # type: ignore
|
|
@@ -146,21 +152,26 @@ class ECListBox(ECCoreWidget):
|
|
|
146
152
|
def isClearable(self):
|
|
147
153
|
return True
|
|
148
154
|
|
|
149
|
-
# Get the count of items in the list box
|
|
150
|
-
def getCount(self):
|
|
151
|
-
v = self.getContent().count() # type: ignore
|
|
152
|
-
return v
|
|
153
|
-
|
|
154
155
|
# Get the selected item in the list box
|
|
155
156
|
def getContent(self):
|
|
156
|
-
widget = self.getValue()
|
|
157
|
-
content = widget.selectedItems()[0].text() if widget.selectedItems() else None
|
|
157
|
+
widget = self.getValue() # type: ignore
|
|
158
|
+
content = widget.selectedItems()[0].text() if widget.selectedItems() else None # type: ignore
|
|
158
159
|
return content
|
|
159
160
|
|
|
160
161
|
# Get the text of the widget
|
|
161
162
|
def getText(self):
|
|
162
|
-
return self.
|
|
163
|
-
|
|
163
|
+
return self.getContent() # type: ignore
|
|
164
|
+
|
|
165
|
+
# Get the count of items in the list box
|
|
166
|
+
def getCount(self):
|
|
167
|
+
v = self.getContent().count() # type: ignore
|
|
168
|
+
return v
|
|
169
|
+
|
|
170
|
+
# Get the index of the selected item
|
|
171
|
+
def getIndex(self):
|
|
172
|
+
widget = self.getValue() # type: ignore
|
|
173
|
+
index = widget.currentRow() # type: ignore
|
|
174
|
+
return index
|
|
164
175
|
|
|
165
176
|
###############################################################################
|
|
166
177
|
# A combo box variable
|
easycoder/ec_graphics.py
CHANGED
|
@@ -198,7 +198,6 @@ class Graphics(Handler):
|
|
|
198
198
|
# Set a graphic element as the value of a record
|
|
199
199
|
def setGraphicElement(self, record, element):
|
|
200
200
|
object = self.getObject(record)
|
|
201
|
-
# object.setValue(ECValue(domain=self.getName(), type='object', content=element))
|
|
202
201
|
object.setValue(element)
|
|
203
202
|
|
|
204
203
|
def dialogTypes(self):
|
|
@@ -769,7 +768,8 @@ class Graphics(Handler):
|
|
|
769
768
|
|
|
770
769
|
def r_createLineEdit(self, command, record):
|
|
771
770
|
lineinput = ECLineEditWidget()
|
|
772
|
-
|
|
771
|
+
text = self.textify(command['text'])
|
|
772
|
+
lineinput.setText(str(text))
|
|
773
773
|
fm = lineinput.fontMetrics()
|
|
774
774
|
m = lineinput.textMargins()
|
|
775
775
|
c = lineinput.contentsMargins()
|
|
@@ -1128,9 +1128,10 @@ class Graphics(Handler):
|
|
|
1128
1128
|
return self.nextPC()
|
|
1129
1129
|
|
|
1130
1130
|
# remove [the] [current/selected] [item] [from/in] {combobox}/{listbox}
|
|
1131
|
+
# Graphics-reserved syntax: optional article pattern is plugin-safe (core-only command)
|
|
1131
1132
|
def k_remove(self, command):
|
|
1132
1133
|
command['variant'] = None
|
|
1133
|
-
self.
|
|
1134
|
+
self.skipArticles() # Optional 'the', 'a', 'an' — syntactic sugar
|
|
1134
1135
|
self.skip(['current', 'selected'])
|
|
1135
1136
|
self.skip('item')
|
|
1136
1137
|
self.skip(['from', 'in'])
|
|
@@ -1201,7 +1202,10 @@ class Graphics(Handler):
|
|
|
1201
1202
|
# set {listbox} to {list}
|
|
1202
1203
|
# set blocked true/false
|
|
1203
1204
|
def k_set(self, command):
|
|
1204
|
-
|
|
1205
|
+
# Graphics-reserved syntax: optional article pattern with 'of'/'to' prepositions
|
|
1206
|
+
# Forms like 'set the layout of Window to MainPanel' and 'set layout of Window to MainPanel' are equivalent
|
|
1207
|
+
# Plugin-safe: graphics is a core-only module
|
|
1208
|
+
self.skipArticles() # Optional 'the', 'a', 'an' — syntactic sugar for readability
|
|
1205
1209
|
token = self.nextToken()
|
|
1206
1210
|
command['what'] = token
|
|
1207
1211
|
if token in ['width', 'height']:
|
|
@@ -1363,15 +1367,16 @@ class Graphics(Handler):
|
|
|
1363
1367
|
keyword = record['keyword']
|
|
1364
1368
|
setText = getattr(widget, "setText", None)
|
|
1365
1369
|
if callable(setText):
|
|
1366
|
-
widget.setText(text) # type: ignore
|
|
1370
|
+
widget.setText(str(text)) # type: ignore
|
|
1367
1371
|
elif self.isObjectType(record, ECMultiline):
|
|
1368
|
-
widget.setPlainText(text) # type: ignore
|
|
1372
|
+
widget.setPlainText(str(text)) # type: ignore
|
|
1369
1373
|
if self.isObjectType(record, ECPushButton):
|
|
1370
|
-
widget.setAccessibleName(text) # type: ignore
|
|
1374
|
+
widget.setAccessibleName(str(text)) # type: ignore
|
|
1371
1375
|
elif what == 'state':
|
|
1372
1376
|
record = self.getVariable(command['name'])
|
|
1373
1377
|
if self.isObjectType(record, ECCheckBox):
|
|
1374
1378
|
state = self.textify(command['value'])
|
|
1379
|
+
state = False if state == None else True
|
|
1375
1380
|
self.getInnerObject(record).setChecked(state) # type: ignore
|
|
1376
1381
|
elif what == 'alignment':
|
|
1377
1382
|
widget = self.getVariable(command['name'])['widget']
|
|
@@ -1468,7 +1473,7 @@ class Graphics(Handler):
|
|
|
1468
1473
|
if choice == QMessageBox.StandardButton.Ok: result = 'OK'
|
|
1469
1474
|
else: result = ''
|
|
1470
1475
|
else: result = 'Cancel'
|
|
1471
|
-
v = ECValue(domain='graphics', type=
|
|
1476
|
+
v = ECValue(domain='graphics', type=str, content=result)
|
|
1472
1477
|
self.putSymbolValue(target, v)
|
|
1473
1478
|
elif 'window' in command:
|
|
1474
1479
|
window = self.getInnerObject(self.getVariable(command['window'])['object'])
|
|
@@ -1525,6 +1530,7 @@ class Graphics(Handler):
|
|
|
1525
1530
|
self.skip('of')
|
|
1526
1531
|
elif token in ['current', 'selected']:
|
|
1527
1532
|
token = self.nextToken()
|
|
1533
|
+
value.option = token
|
|
1528
1534
|
if token == 'item': self.skip('in')
|
|
1529
1535
|
elif token == 'index': self.skip('of')
|
|
1530
1536
|
if self.nextIsSymbol():
|
|
@@ -1548,6 +1554,14 @@ class Graphics(Handler):
|
|
|
1548
1554
|
): # type: ignore
|
|
1549
1555
|
value.setContent(ECValue(domain=self.getName(), type='object', content=record['name']))
|
|
1550
1556
|
return value
|
|
1557
|
+
elif token == 'index':
|
|
1558
|
+
self.skip('of')
|
|
1559
|
+
value.element = self.getValue()
|
|
1560
|
+
if self.nextIsSymbol():
|
|
1561
|
+
record = self.getSymbolRecord()
|
|
1562
|
+
if self.isObjectType(record, (ECListBox, ECComboBox)): # type: ignore
|
|
1563
|
+
value.setContent(ECValue(domain=self.getName(), type='object', content=record['name']))
|
|
1564
|
+
return value
|
|
1551
1565
|
return None
|
|
1552
1566
|
|
|
1553
1567
|
#############################################################################
|
|
@@ -1564,33 +1578,33 @@ class Graphics(Handler):
|
|
|
1564
1578
|
keyword = record['keyword']
|
|
1565
1579
|
if self.isObjectType(record, ECPushButton):
|
|
1566
1580
|
pushbutton = self.getInnerObject(record)
|
|
1567
|
-
v = ECValue(domain=self.getName(), type=
|
|
1581
|
+
v = ECValue(domain=self.getName(), type=str, content=pushbutton.accessibleName())
|
|
1568
1582
|
return v
|
|
1569
1583
|
elif self.isObjectType(record, ECLineInput):
|
|
1570
1584
|
lineinput = self.getInnerObject(record)
|
|
1571
|
-
v = ECValue(domain=self.getName(), type=
|
|
1585
|
+
v = ECValue(domain=self.getName(), type=str, content=lineinput.displayText())
|
|
1572
1586
|
return v
|
|
1573
1587
|
elif self.isObjectType(record, ECMultiline):
|
|
1574
1588
|
multiline = self.getInnerObject(record)
|
|
1575
|
-
v = ECValue(domain=self.getName(), type=
|
|
1589
|
+
v = ECValue(domain=self.getName(), type=str, content=multiline.toPlainText())
|
|
1576
1590
|
return v
|
|
1577
1591
|
elif self.isObjectType(record, ECComboBox):
|
|
1578
1592
|
combobox = self.getInnerObject(record)
|
|
1579
|
-
v = ECValue(domain=self.getName(), type=
|
|
1593
|
+
v = ECValue(domain=self.getName(), type=str, content=combobox.currentText())
|
|
1580
1594
|
return v
|
|
1581
1595
|
elif self.isObjectType(record, ECListBox):
|
|
1582
1596
|
listbox = self.getInnerObject(record)
|
|
1583
1597
|
content = listbox.currentItem().text() # type: ignore
|
|
1584
|
-
v = ECValue(domain=self.getName(), type=
|
|
1598
|
+
v = ECValue(domain=self.getName(), type=str, content=content)
|
|
1585
1599
|
return v
|
|
1586
1600
|
elif self.isObjectType(record, ECCheckBox):
|
|
1587
1601
|
checkbox =self.getInnerObject(record)
|
|
1588
1602
|
content = checkbox.isChecked() # type: ignore
|
|
1589
|
-
v = ECValue(domain=self.getName(), type=
|
|
1603
|
+
v = ECValue(domain=self.getName(), type=bool, content=content)
|
|
1590
1604
|
return v
|
|
1591
1605
|
elif self.isObjectType(record, ECDialog):
|
|
1592
1606
|
content = record['result']
|
|
1593
|
-
v = ECValue(domain=self.getName(), type=
|
|
1607
|
+
v = ECValue(domain=self.getName(), type=str, content=content)
|
|
1594
1608
|
return v
|
|
1595
1609
|
return None
|
|
1596
1610
|
|
|
@@ -1602,22 +1616,24 @@ class Graphics(Handler):
|
|
|
1602
1616
|
if isinstance(object, (ECListBox, ECComboBox)):
|
|
1603
1617
|
widget = self.getInnerObject(object)
|
|
1604
1618
|
value = widget.count() # type: ignore
|
|
1605
|
-
return ECValue(domain=self.getName(), type=
|
|
1619
|
+
return ECValue(domain=self.getName(), type=int, content=value) # type: ignore
|
|
1606
1620
|
else: raise RuntimeError(self.program, f"Object is not a listbox or combobox")
|
|
1607
1621
|
|
|
1608
1622
|
def v_current(self, v):
|
|
1609
1623
|
content = v.getContent()
|
|
1610
1624
|
if isinstance(content, ECValue) and content.getType() == 'object':
|
|
1611
1625
|
record = self.getVariable(content.getContent())
|
|
1612
|
-
keyword = record['keyword']
|
|
1613
1626
|
object = self.getObject(record)
|
|
1614
|
-
|
|
1615
|
-
if isinstance(
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
return ECValue(domain=self.getName(), type=
|
|
1627
|
+
option = v.option
|
|
1628
|
+
if isinstance(object, (ECListBox)):
|
|
1629
|
+
if option == 'item':
|
|
1630
|
+
content = object.getText() # type: ignore
|
|
1631
|
+
elif option == 'index':
|
|
1632
|
+
content = object.getIndex() # type: ignore
|
|
1633
|
+
return ECValue(domain=self.getName(), type=int, content=content)
|
|
1634
|
+
elif isinstance(object, (ECComboBox)):
|
|
1635
|
+
content = str(object.currentText()) # type: ignore
|
|
1636
|
+
return ECValue(domain=self.getName(), type=int, content=content)
|
|
1621
1637
|
else: raise RuntimeError(self.program, f"Object is not a listbox or combobox")
|
|
1622
1638
|
|
|
1623
1639
|
def v_element(self, v):
|
|
@@ -1628,7 +1644,7 @@ class Graphics(Handler):
|
|
|
1628
1644
|
record = self.getVariable(v.getContent())
|
|
1629
1645
|
object = self.getObject(record)
|
|
1630
1646
|
value = object.isEmpty()
|
|
1631
|
-
return ECValue(domain=self.getName(), type=
|
|
1647
|
+
return ECValue(domain=self.getName(), type=bool, content=value) # type: ignore
|
|
1632
1648
|
return None
|
|
1633
1649
|
|
|
1634
1650
|
def v_selected(self, v): return self.v_current(v)
|
|
@@ -1639,7 +1655,7 @@ class Graphics(Handler):
|
|
|
1639
1655
|
record = self.getVariable(content.getContent())
|
|
1640
1656
|
object = self.getObject(record)
|
|
1641
1657
|
value = object.getText()
|
|
1642
|
-
return ECValue(domain=self.getName(), type=
|
|
1658
|
+
return ECValue(domain=self.getName(), type=int, content=value) # type: ignore
|
|
1643
1659
|
|
|
1644
1660
|
#############################################################################
|
|
1645
1661
|
# Get the value of an unknown item (domain-specific)
|
easycoder/ec_handler.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import sys, json
|
|
2
|
-
from .ec_classes import
|
|
2
|
+
from .ec_classes import normalize_type
|
|
3
3
|
|
|
4
4
|
class Handler:
|
|
5
5
|
|
|
@@ -9,6 +9,7 @@ class Handler:
|
|
|
9
9
|
self.getToken = compiler.getToken
|
|
10
10
|
self.nextToken = compiler.nextToken
|
|
11
11
|
self.skip = compiler.skip
|
|
12
|
+
self.skipArticles = compiler.skipArticles
|
|
12
13
|
self.peek = compiler.peek
|
|
13
14
|
self.getValue = compiler.getValue
|
|
14
15
|
self.nextValue = compiler.nextValue
|
|
@@ -71,8 +72,8 @@ class Handler:
|
|
|
71
72
|
|
|
72
73
|
# Get a condition handler
|
|
73
74
|
def conditionHandler(self, name):
|
|
74
|
-
return getattr(self, f'c_{name}')
|
|
75
|
+
return getattr(self, f'c_{normalize_type(name)}')
|
|
75
76
|
|
|
76
77
|
# Get the value of an unknown item (domain-specific)
|
|
77
78
|
def getUnknownValue(self, value):
|
|
78
|
-
return
|
|
79
|
+
return value
|
easycoder/ec_mqtt.py
ADDED
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
from easycoder import Handler, ECObject, ECValue, RuntimeError
|
|
2
|
+
import paho.mqtt.client as mqtt
|
|
3
|
+
|
|
4
|
+
#############################################################################
|
|
5
|
+
# MQTT client class
|
|
6
|
+
class MQTTClient():
|
|
7
|
+
def __init__(self):
|
|
8
|
+
super().__init__()
|
|
9
|
+
|
|
10
|
+
def create(self, program, clientID, broker, port, topics):
|
|
11
|
+
self.program = program
|
|
12
|
+
self.clientID = clientID
|
|
13
|
+
self.broker = broker
|
|
14
|
+
self.port = port
|
|
15
|
+
self.topics = topics
|
|
16
|
+
self.onMessagePC = None
|
|
17
|
+
self.client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id=self.clientID) # type: ignore
|
|
18
|
+
|
|
19
|
+
# Setup callbacks
|
|
20
|
+
self.client.on_connect = self.on_connect
|
|
21
|
+
self.client.on_message = self.on_message
|
|
22
|
+
|
|
23
|
+
def on_connect(self, client, userdata, flags, reason_code, properties):
|
|
24
|
+
print(f"Client {self.clientID} connected")
|
|
25
|
+
for item in self.topics:
|
|
26
|
+
topic = self.program.getObject(self.program.getVariable(item))
|
|
27
|
+
self.client.subscribe(topic.getName(), qos=topic.getQOS())
|
|
28
|
+
print(f"Subscribed to topic: {topic.getName()} with QoS {topic.getQOS()}")
|
|
29
|
+
|
|
30
|
+
def on_message(self, client, userdata, msg):
|
|
31
|
+
# print(f"Message received on topic {msg.topic}: {msg.payload.decode()}")
|
|
32
|
+
if self.onMessagePC is not None:
|
|
33
|
+
self.message = msg
|
|
34
|
+
self.program.run(self.onMessagePC)
|
|
35
|
+
self.program.flushCB()
|
|
36
|
+
|
|
37
|
+
def getMessageTopic(self):
|
|
38
|
+
return self.message.topic
|
|
39
|
+
|
|
40
|
+
def getMessagePayload(self):
|
|
41
|
+
return self.message.payload.decode('utf-8')
|
|
42
|
+
|
|
43
|
+
def onMessage(self, pc):
|
|
44
|
+
self.onMessagePC = pc
|
|
45
|
+
|
|
46
|
+
def sendMessage(self, topic, message, qos):
|
|
47
|
+
self.client.publish(topic, message, qos=qos)
|
|
48
|
+
|
|
49
|
+
def run(self):
|
|
50
|
+
self.client.connect(self.broker, int(self.port), 60)
|
|
51
|
+
self.client.loop_start()
|
|
52
|
+
|
|
53
|
+
###############################################################################
|
|
54
|
+
# An MQTT topic
|
|
55
|
+
class ECTopic(ECObject):
|
|
56
|
+
def __init__(self):
|
|
57
|
+
super().__init__()
|
|
58
|
+
|
|
59
|
+
def create(self, name, qos=1):
|
|
60
|
+
super().__init__()
|
|
61
|
+
self.name = name
|
|
62
|
+
self.qos = qos
|
|
63
|
+
|
|
64
|
+
def getName(self):
|
|
65
|
+
return self.name
|
|
66
|
+
|
|
67
|
+
def getQOS(self):
|
|
68
|
+
return self.qos
|
|
69
|
+
|
|
70
|
+
###############################################################################
|
|
71
|
+
# The MQTT compiler and rutime handlers
|
|
72
|
+
class MQTT(Handler):
|
|
73
|
+
|
|
74
|
+
def __init__(self, compiler):
|
|
75
|
+
Handler.__init__(self, compiler)
|
|
76
|
+
self.spoke = None
|
|
77
|
+
|
|
78
|
+
def getName(self):
|
|
79
|
+
return 'mqtt'
|
|
80
|
+
|
|
81
|
+
#############################################################################
|
|
82
|
+
# Keyword handlers
|
|
83
|
+
|
|
84
|
+
# init {topic} name {name} qos {qos}
|
|
85
|
+
def k_init(self, command):
|
|
86
|
+
if self.nextIsSymbol():
|
|
87
|
+
record = self.getSymbolRecord()
|
|
88
|
+
self.checkObjectType(record, ECTopic)
|
|
89
|
+
command['topic'] = record['name']
|
|
90
|
+
self.skip('name')
|
|
91
|
+
command['name'] = self.nextValue()
|
|
92
|
+
self.skip('qos')
|
|
93
|
+
command['qos'] = self.nextValue()
|
|
94
|
+
self.add(command)
|
|
95
|
+
return True
|
|
96
|
+
return False
|
|
97
|
+
|
|
98
|
+
def r_init(self, command):
|
|
99
|
+
record = self.getVariable(command['topic'])
|
|
100
|
+
topic = ECTopic()
|
|
101
|
+
topic.create(self.textify(command['name']), qos=int(self.textify(command['qos'])))
|
|
102
|
+
record['object'] = topic
|
|
103
|
+
return self.nextPC()
|
|
104
|
+
|
|
105
|
+
# mqtt id {clientID} broker {broker} port {port} topics {topic} [and {topic} ...]
|
|
106
|
+
def k_mqtt(self, command):
|
|
107
|
+
while True:
|
|
108
|
+
token = self.peek()
|
|
109
|
+
if token == 'id':
|
|
110
|
+
self.nextToken()
|
|
111
|
+
command['clientID'] = self.nextValue()
|
|
112
|
+
elif token == 'broker':
|
|
113
|
+
self.nextToken()
|
|
114
|
+
command['broker'] = self.nextValue()
|
|
115
|
+
elif token == 'port':
|
|
116
|
+
self.nextToken()
|
|
117
|
+
command['port'] = self.nextValue()
|
|
118
|
+
elif token == 'topics':
|
|
119
|
+
self.nextToken()
|
|
120
|
+
topics = []
|
|
121
|
+
while self.nextIsSymbol():
|
|
122
|
+
record = self.getSymbolRecord()
|
|
123
|
+
self.checkObjectType(record, ECTopic())
|
|
124
|
+
topics.append(record['name'])
|
|
125
|
+
if self.peek() == 'and': self.nextToken()
|
|
126
|
+
else:break
|
|
127
|
+
command['topics'] = topics
|
|
128
|
+
else:
|
|
129
|
+
self.add(command)
|
|
130
|
+
return True
|
|
131
|
+
return False
|
|
132
|
+
|
|
133
|
+
def r_mqtt(self, command):
|
|
134
|
+
if hasattr(self.program, 'mqttClient'):
|
|
135
|
+
raise RuntimeError(self.program, 'MQQT client already defined')
|
|
136
|
+
clientID = self.textify(command['clientID'])
|
|
137
|
+
broker = self.textify(command['broker'])
|
|
138
|
+
port = self.textify(command['port'])
|
|
139
|
+
topics = command['topics']
|
|
140
|
+
client = MQTTClient()
|
|
141
|
+
client.create(self.program, clientID, broker, port, topics)
|
|
142
|
+
client.run()
|
|
143
|
+
self.program.mqttClient = client
|
|
144
|
+
return self.nextPC()
|
|
145
|
+
|
|
146
|
+
# on mqtt message {action}
|
|
147
|
+
def k_on(self, command):
|
|
148
|
+
token = self.peek()
|
|
149
|
+
if token == 'mqtt':
|
|
150
|
+
self.nextToken()
|
|
151
|
+
if self.nextIs('message'):
|
|
152
|
+
self.nextToken()
|
|
153
|
+
command['goto'] = 0
|
|
154
|
+
self.add(command)
|
|
155
|
+
cmd = {}
|
|
156
|
+
cmd['domain'] = 'core'
|
|
157
|
+
cmd['lino'] = command['lino']
|
|
158
|
+
cmd['keyword'] = 'gotoPC'
|
|
159
|
+
cmd['goto'] = 0
|
|
160
|
+
cmd['debug'] = False
|
|
161
|
+
self.add(cmd)
|
|
162
|
+
# Add the action and a 'stop'
|
|
163
|
+
self.compileOne()
|
|
164
|
+
cmd = {}
|
|
165
|
+
cmd['domain'] = 'core'
|
|
166
|
+
cmd['lino'] = command['lino']
|
|
167
|
+
cmd['keyword'] = 'stop'
|
|
168
|
+
cmd['debug'] = False
|
|
169
|
+
self.add(cmd)
|
|
170
|
+
# Fixup the link
|
|
171
|
+
command['goto'] = self.getCodeSize()
|
|
172
|
+
return True
|
|
173
|
+
return False
|
|
174
|
+
|
|
175
|
+
def r_on(self, command):
|
|
176
|
+
self.program.mqttClient.onMessage(self.nextPC()+1)
|
|
177
|
+
return command['goto']
|
|
178
|
+
|
|
179
|
+
# send {message} to {topic}
|
|
180
|
+
def k_send(self, command):
|
|
181
|
+
if self.nextIs('mqtt'):
|
|
182
|
+
command['message'] = self.nextValue()
|
|
183
|
+
self.skip('from')
|
|
184
|
+
if self.nextIsSymbol():
|
|
185
|
+
record = self.getSymbolRecord()
|
|
186
|
+
self.checkObjectType(record, MQTTClient)
|
|
187
|
+
command['from'] = record['name']
|
|
188
|
+
self.skip('to')
|
|
189
|
+
if self.nextIsSymbol():
|
|
190
|
+
record = self.getSymbolRecord()
|
|
191
|
+
self.checkObjectType(record, MQTTClient)
|
|
192
|
+
command['to'] = record['name']
|
|
193
|
+
self.add(command)
|
|
194
|
+
return True
|
|
195
|
+
return False
|
|
196
|
+
|
|
197
|
+
def r_send(self, command):
|
|
198
|
+
if not hasattr(self.program, 'mqttClient'):
|
|
199
|
+
raise RuntimeError(self.program, 'No MQTT client defined')
|
|
200
|
+
topic = self.getObject(self.getVariable(command['to']))
|
|
201
|
+
message = self.textify(command['message'])
|
|
202
|
+
self.program.mqttClient.sendMessage(topic.getName(), message, topic.getQOS())
|
|
203
|
+
return self.nextPC()
|
|
204
|
+
|
|
205
|
+
# Declare a topic variable
|
|
206
|
+
def k_topic(self, command):
|
|
207
|
+
self.compiler.addValueType()
|
|
208
|
+
return self.compileVariable(command, 'ECTopic')
|
|
209
|
+
|
|
210
|
+
def r_topic(self, command):
|
|
211
|
+
return self.nextPC()
|
|
212
|
+
|
|
213
|
+
#############################################################################
|
|
214
|
+
# Compile a value in this domain
|
|
215
|
+
def compileValue(self):
|
|
216
|
+
token = self.nextToken()
|
|
217
|
+
if token == 'mqtt':
|
|
218
|
+
value = ECValue(domain=self.getName())
|
|
219
|
+
token = self.nextToken()
|
|
220
|
+
if token in ['topic', 'message']:
|
|
221
|
+
value.setType(token)
|
|
222
|
+
return value
|
|
223
|
+
else:
|
|
224
|
+
return self.getValue()
|
|
225
|
+
return None
|
|
226
|
+
|
|
227
|
+
#############################################################################
|
|
228
|
+
# Modify a value or leave it unchanged.
|
|
229
|
+
def modifyValue(self, value):
|
|
230
|
+
return value
|
|
231
|
+
|
|
232
|
+
#############################################################################
|
|
233
|
+
# Value handlers
|
|
234
|
+
|
|
235
|
+
def v_message(self, v):
|
|
236
|
+
return self.program.mqttClient.getMessagePayload()
|
|
237
|
+
|
|
238
|
+
def v_topic(self, v):
|
|
239
|
+
return self.program.mqttClient.getMessageTopic()
|
|
240
|
+
|
|
241
|
+
#############################################################################
|
|
242
|
+
# Compile a condition
|
|
243
|
+
def compileCondition(self):
|
|
244
|
+
condition = {}
|
|
245
|
+
return condition
|
|
246
|
+
|
|
247
|
+
#############################################################################
|
|
248
|
+
# Condition handlers
|