dashio 3.3.1__tar.gz → 3.3.2__tar.gz

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.
Files changed (81) hide show
  1. dashio-3.3.2/PKG-INFO +197 -0
  2. dashio-3.3.2/README.md +181 -0
  3. {dashio-3.3.1 → dashio-3.3.2}/dashio/iotcontrol/chart.py +36 -3
  4. {dashio-3.3.1 → dashio-3.3.2}/dashio/iotcontrol/enums.py +0 -1
  5. {dashio-3.3.1 → dashio-3.3.2}/dashio/iotcontrol/time_graph.py +54 -3
  6. dashio-3.3.2/dashio.egg-info/PKG-INFO +197 -0
  7. {dashio-3.3.1 → dashio-3.3.2}/dashio.egg-info/SOURCES.txt +23 -1
  8. {dashio-3.3.1 → dashio-3.3.2}/setup.py +1 -1
  9. dashio-3.3.2/tests/test_alarm.py +12 -0
  10. dashio-3.3.2/tests/test_button.py +44 -0
  11. dashio-3.3.2/tests/test_button_group.py +26 -0
  12. dashio-3.3.2/tests/test_chart.py +71 -0
  13. dashio-3.3.2/tests/test_control.py +18 -0
  14. dashio-3.3.2/tests/test_dashconnection.py +18 -0
  15. dashio-3.3.2/tests/test_dashdevice.py +30 -0
  16. dashio-3.3.2/tests/test_device_view.py +77 -0
  17. dashio-3.3.2/tests/test_dial.py +70 -0
  18. dashio-3.3.2/tests/test_direction.py +51 -0
  19. dashio-3.3.2/tests/test_event_log.py +33 -0
  20. dashio-3.3.2/tests/test_knob.py +65 -0
  21. dashio-3.3.2/tests/test_label.py +25 -0
  22. dashio-3.3.2/tests/test_map.py +75 -0
  23. dashio-3.3.2/tests/test_menu.py +37 -0
  24. dashio-3.3.2/tests/test_mqttconntection.py +12 -0
  25. dashio-3.3.2/tests/test_selector.py +26 -0
  26. dashio-3.3.2/tests/test_slider.py +77 -0
  27. dashio-3.3.2/tests/test_tcpconnection.py +12 -0
  28. dashio-3.3.2/tests/test_textbox.py +62 -0
  29. dashio-3.3.2/tests/test_time_graph.py +46 -0
  30. dashio-3.3.2/tests/test_zqmconnection.py +0 -0
  31. dashio-3.3.1/PKG-INFO +0 -924
  32. dashio-3.3.1/README.md +0 -908
  33. dashio-3.3.1/dashio.egg-info/PKG-INFO +0 -924
  34. {dashio-3.3.1 → dashio-3.3.2}/LICENSE +0 -0
  35. {dashio-3.3.1 → dashio-3.3.2}/dashio/__init__.py +0 -0
  36. {dashio-3.3.1 → dashio-3.3.2}/dashio/action_station.py +0 -0
  37. {dashio-3.3.1 → dashio-3.3.2}/dashio/action_station_services/__init__.py +0 -0
  38. {dashio-3.3.1 → dashio-3.3.2}/dashio/action_station_services/action_station_service_config.py +0 -0
  39. {dashio-3.3.1 → dashio-3.3.2}/dashio/action_station_services/as_servicel.py +0 -0
  40. {dashio-3.3.1 → dashio-3.3.2}/dashio/action_station_services/clock_servicel.py +0 -0
  41. {dashio-3.3.1 → dashio-3.3.2}/dashio/action_station_services/modbus_service.py +0 -0
  42. {dashio-3.3.1 → dashio-3.3.2}/dashio/action_station_services/task_service.py +0 -0
  43. {dashio-3.3.1 → dashio-3.3.2}/dashio/action_station_services/timer_service.py +0 -0
  44. {dashio-3.3.1 → dashio-3.3.2}/dashio/bleconnection.py +0 -0
  45. {dashio-3.3.1 → dashio-3.3.2}/dashio/constants.py +0 -0
  46. {dashio-3.3.1 → dashio-3.3.2}/dashio/dashconnection.py +0 -0
  47. {dashio-3.3.1 → dashio-3.3.2}/dashio/device.py +0 -0
  48. {dashio-3.3.1 → dashio-3.3.2}/dashio/iotcontrol/__init__.py +0 -0
  49. {dashio-3.3.1 → dashio-3.3.2}/dashio/iotcontrol/alarm.py +0 -0
  50. {dashio-3.3.1 → dashio-3.3.2}/dashio/iotcontrol/audio_visual_display.py +0 -0
  51. {dashio-3.3.1 → dashio-3.3.2}/dashio/iotcontrol/button.py +0 -0
  52. {dashio-3.3.1 → dashio-3.3.2}/dashio/iotcontrol/button_group.py +0 -0
  53. {dashio-3.3.1 → dashio-3.3.2}/dashio/iotcontrol/color_picker.py +0 -0
  54. {dashio-3.3.1 → dashio-3.3.2}/dashio/iotcontrol/control.py +0 -0
  55. {dashio-3.3.1 → dashio-3.3.2}/dashio/iotcontrol/device_view.py +0 -0
  56. {dashio-3.3.1 → dashio-3.3.2}/dashio/iotcontrol/dial.py +0 -0
  57. {dashio-3.3.1 → dashio-3.3.2}/dashio/iotcontrol/direction.py +0 -0
  58. {dashio-3.3.1 → dashio-3.3.2}/dashio/iotcontrol/event.py +0 -0
  59. {dashio-3.3.1 → dashio-3.3.2}/dashio/iotcontrol/event_log.py +0 -0
  60. {dashio-3.3.1 → dashio-3.3.2}/dashio/iotcontrol/knob.py +0 -0
  61. {dashio-3.3.1 → dashio-3.3.2}/dashio/iotcontrol/label.py +0 -0
  62. {dashio-3.3.1 → dashio-3.3.2}/dashio/iotcontrol/map.py +0 -0
  63. {dashio-3.3.1 → dashio-3.3.2}/dashio/iotcontrol/menu.py +0 -0
  64. {dashio-3.3.1 → dashio-3.3.2}/dashio/iotcontrol/ring_buffer.py +0 -0
  65. {dashio-3.3.1 → dashio-3.3.2}/dashio/iotcontrol/selector.py +0 -0
  66. {dashio-3.3.1 → dashio-3.3.2}/dashio/iotcontrol/slider.py +0 -0
  67. {dashio-3.3.1 → dashio-3.3.2}/dashio/iotcontrol/textbox.py +0 -0
  68. {dashio-3.3.1 → dashio-3.3.2}/dashio/ip.py +0 -0
  69. {dashio-3.3.1 → dashio-3.3.2}/dashio/load_config.py +0 -0
  70. {dashio-3.3.1 → dashio-3.3.2}/dashio/mqttconnection.py +0 -0
  71. {dashio-3.3.1 → dashio-3.3.2}/dashio/py.typed +0 -0
  72. {dashio-3.3.1 → dashio-3.3.2}/dashio/serialconnection.py +0 -0
  73. {dashio-3.3.1 → dashio-3.3.2}/dashio/tcpconnection.py +0 -0
  74. {dashio-3.3.1 → dashio-3.3.2}/dashio/zeroconf_service.py +0 -0
  75. {dashio-3.3.1 → dashio-3.3.2}/dashio/zmqconnection.py +0 -0
  76. {dashio-3.3.1 → dashio-3.3.2}/dashio.egg-info/dependency_links.txt +0 -0
  77. {dashio-3.3.1 → dashio-3.3.2}/dashio.egg-info/not-zip-safe +0 -0
  78. {dashio-3.3.1 → dashio-3.3.2}/dashio.egg-info/requires.txt +0 -0
  79. {dashio-3.3.1 → dashio-3.3.2}/dashio.egg-info/top_level.txt +0 -0
  80. {dashio-3.3.1 → dashio-3.3.2}/pyproject.toml +0 -0
  81. {dashio-3.3.1 → dashio-3.3.2}/setup.cfg +0 -0
dashio-3.3.2/PKG-INFO ADDED
@@ -0,0 +1,197 @@
1
+ Metadata-Version: 2.1
2
+ Name: dashio
3
+ Version: 3.3.2
4
+ Summary: DashIO interface library
5
+ Home-page: https://dashio.io
6
+ Download-URL: https://github.com/dashio-connect/python-dashio
7
+ Author: James Boulton
8
+ Author-email: james@dashio.com
9
+ License: MIT
10
+ Classifier: Programming Language :: Python :: 3.6
11
+ Classifier: Operating System :: OS Independent
12
+ Requires-Python: >3.6.0
13
+ Description-Content-Type: text/markdown
14
+ Provides-Extra: testing
15
+ License-File: LICENSE
16
+
17
+ # DashIO
18
+
19
+ ![Tests](https://github.com/dashio-connect/python-dashio/actions/workflows/tests.yml/badge.svg)
20
+
21
+ [**DashIO**](http://dashio.io) - It is a quick effortless way to connect your IoT device to your phone, tablet or iPad using the free **Dash** app. It allows easy setup of controls such as Dials, Text Boxes, Charts, Graphs, Notifications..., from your IoT device. You can define the look and layout of the controls on your phone from your IoT device. There are three methods to connect to your phone; Bluetooth Low Energy (BLE), TCP or MQTT.
22
+
23
+ ## Getting Started
24
+
25
+ For the big picture on **DashIO**, take a look at our website: <a href="https://dashio.io">dashio.io</a>
26
+
27
+ ## Documentation
28
+
29
+ For all documentation and software guides: <a href="https://dashio.io/documents">dashio.io/documents</a>
30
+
31
+ For the **DashIO** Python guide: <a href="https://dashio.io/guide-python">dashio.io/guide-python</a>
32
+
33
+ For the **DashIO** Python library: <a href="https://dashio.io/python-library/">dashio.io/python-library</a>
34
+
35
+ ## Examples
36
+
37
+ There are plenty of examples in the github repository under the Examples directory.
38
+
39
+ ## Dash IoT Application
40
+
41
+ The **Dash** app is free and available for both Apple and Android devices. Use it to create beautiful and powerful user interfaces to you IoT devices.
42
+
43
+ Dashio Phone | Dashio Tablet
44
+ :-------------------------:|:-------------------------:
45
+ <img src="https://dashio.io/wp-content/uploads/2020/11/IMG_4154.jpeg" width="150" /> | <img src="https://dashio.io/wp-content/uploads/2020/12/IMG_4203.jpeg" width="450" />
46
+
47
+ ## Requirements
48
+
49
+ * python3.6 and above
50
+ * paho-mqtt
51
+ * pyzmq
52
+ * python-dateutil
53
+ * zeroconf
54
+ * shortuuid
55
+
56
+ ## Install
57
+
58
+ `pip3 install dashio`
59
+
60
+ Or
61
+
62
+ ```sh
63
+ git clone https://github.com/dashio-connect/python-dashio.git
64
+ cd python-dashio
65
+ pip3 install .
66
+ ```
67
+
68
+ ## A Quick Guide
69
+
70
+ This guide covers the **DashIO** python library. For information on the [***Dash***](https://dashio.io/dashboard) phone app please visit the website.
71
+
72
+ ### Basics
73
+
74
+ So what is **DashIO**? It is a quick effortless way to connect your IoT device to your phone. It allows easy setup of controls such as Dials, Text Boxes, Maps, Graphs, Notifications..., from your Device. You can define the look and layout of the controls on your phone from your IoT device. There are three methods to connect to your phone tcp, mqtt, dash, and BLE. What's Dash then? Dash is a mqtt server with extra bits added in to allow you to send notifications, share your devices, and save your settings from your phone via the **Dash** app.
75
+
76
+ Show me some code.
77
+
78
+ ```python
79
+ # Examples/ex01.py
80
+ import dashio
81
+ import random
82
+ import time
83
+
84
+ device = dashio.Device("aDeviceType", "aDeviceID", "aDeviceName")
85
+ tcp_con = dashio.TCPConnection()
86
+ tcp_con.add_device(device)
87
+ first_dial_control = dashio.Dial("FirstDial")
88
+ device.add_control(first_dial_control)
89
+
90
+ while True:
91
+ first_dial_control.dial_value = random.random() * 100
92
+ time.sleep(5)
93
+ ```
94
+
95
+ This is about the fewest lines of code to get talking to the app. There is a lot happening under the hood to make this work. After the import we create a device with three attributes:
96
+
97
+ * "aDeviceType": a common name device_type for all IoT devices using this code which is used for device discovery
98
+ * "aDeviceID": a device_ID to uniquely identify this device, preferably a UUID.
99
+ * "aDeviceName": The name of this device, which can be changed at any time.
100
+
101
+ These attributes describe the device to the app and allow you to distinguish one of your devices from another.
102
+
103
+ The next two lines create a TCP connection and then add the device to the connection. This device is discoverable by the Dash app. You can also discover your IoT device using a third party Bonjour/Zeroconf discovery tool. The mDNS service will be "DashIO.tcp."
104
+
105
+ Though this device is discoverable by the app it would be nice to have the DashIO app automatically setup a new DeviceView and place your control on the new DeviceView. To do that we need to add a few more lines of code:
106
+
107
+ ```python
108
+ # Examples/ex02.py
109
+ import dashio
110
+ import random
111
+ import time
112
+
113
+ device = dashio.Device("aDeviceType", "aDeviceID", "aDeviceName")
114
+ tcp_con = dashio.TCPConnection()
115
+ tcp_con.add_device(device)
116
+ first_dial_control = dashio.Dial("FirstDial", control_position=dashio.ControlPosition(0.24, 0.36, 0.54, 0.26))
117
+ device.add_control(first_dial_control)
118
+
119
+ dv_dial = dashio.DeviceView("aDeviceViewID", "A Dial")
120
+ dv_dial.add_control(first_dial_control)
121
+ device.add_control(dv_dial)
122
+
123
+ while True:
124
+ first_dial_control.dial_value = random.random() * 100
125
+ time.sleep(5)
126
+ ```
127
+
128
+ First we altered the instantiation of a Dial by including a control_position. This allows us to place the control at a set location. The added lines instantiated a DeviceView control, which we than added the dial control. Finally we added the DeviceView to the device.
129
+
130
+ The next piece of the puzzle to consider is how do we get data from the DashIO app? Lets add a Knob and connect it to the Dial:
131
+
132
+ ```python
133
+ # Examples/ex03.py
134
+ import dashio
135
+ import time
136
+
137
+ device = dashio.Device("aDeviceType", "aDeviceID", "aDeviceName")
138
+ tcp_con = dashio.TCPConnection()
139
+ tcp_con.add_device(device)
140
+ first_dial_control = dashio.Dial("FirstDial", control_position=dashio.ControlPosition(0.24, 0.36, 0.54, 0.26))
141
+ device.add_control(first_dial_control)
142
+
143
+ dv = dashio.DeviceView("aDeviceViewID", "A Dial")
144
+ dv.add_control(first_dial_control)
145
+ device.add_control(dv)
146
+
147
+ def knob_event_handler(msg):
148
+ first_dial_control.dial_value = float(msg[3])
149
+
150
+ aknob = dashio.Knob("aKNB", control_position=dashio.ControlPosition(0.24, 0.14, 0.54, 0.26))
151
+ aknob.add_receive_message_callback += knob_event_handler
152
+ dv.add_control(aknob)
153
+ device.add_control(aknob)
154
+
155
+ while True:
156
+ time.sleep(1)
157
+ ```
158
+
159
+ First we added a function that sets the dial value. Next we added a Knob control and added our new function to be called when it receives data from the DashIO app. We also add it to the DeviceView and to the device. Now when the knob in the DashIO app is moved the dial is set to the same value.
160
+
161
+ ### Using the Config64
162
+
163
+ The **Dash** app can generate a CFG64 text string that defines the controls, the controls layout, and device parameters for the Device. The CFG64 string can be used in a number of ways. If we run the example above and using the **Dash** app to export a layout we can use the layout to setup the device and controls.
164
+
165
+ ```python
166
+ # Examples/ex04.py
167
+ import dashio
168
+ import time
169
+
170
+ cfg64 = "pVNdr5pAEP0rN/tMjHCrbXnjQ60RxQD1Nmn6wIVVN8IuXZar1vjfOwuLeNWmTfo2OztzZnLmnBPybA+Z339oaLbwbYhOqBTHDCMT"\
171
+ "LfxgbnlIQwmjgrNs6kIyni1sSJWYpj7Njj4NcIbjEuoFr7CG8viATL3f11ARc0xF0+TiN5LgFcF7eGuI43QVZxU0fRxoSBBRz7Oe"\
172
+ "ZpS9wvcWk81WBLEgDJn9njFUNUtWEshRqLX9KPLncpEt288Jncux6zgrYYVjW3dB0D9oaAfYDssYh+4Ap9Cakjgbsyxj+7Ie3PbL"\
173
+ "fFtpyy01tCep2F7gBgB3uBtiQDYnsFz/DGyGnhs0vEajb5GKnCUyT6hgXCBzMBwASaSw0pTjsoRZ+mejpw8/9fSebvTRWUPuVEHM"\
174
+ "rWUTeP5EZUaLr000CZZfmshauU0Qek6kOh1PBe5q9fLuurYVTh15XMEzYG8MNw7JL/gxYK0NJylQUOUUFjMMSTNcs8m0l6ZVfinR"\
175
+ "b0Ryc285w2Y8xbzl9WVLBH4Kc7bD7f9uQ9OO9jjZqY+/tEQ8pmWtteQI3MtF3mN08nLhsKo1kkmbHR4NbP/ukCUrAagFmc/GVWlH"\
176
+ "nQ5KJUDEIs7lxPBnBd1IysGdWl5Nf8FxQspaxIDYHmM5Hd34bEx4KdTC/+UphfHAU7X+SXYhuHHFH512b6tnACkYoaK7q/ILaOMV"\
177
+ "8ysUbzSOHrv1X61VUSKkS9C1y6JO/XYULdpoouzijCfScGnNVIhFVQAAheNoe7ImmkiKZteOSqXl9SbAbxCez78B"
178
+
179
+ config_dict = dashio.decode_cfg64(cfg64)
180
+ device = dashio.Device("aDeviceType", "aDeviceID", "aDeviceName", cfg_dict=config_dict)
181
+ tcp_con = dashio.TCPConnection()
182
+ tcp_con.add_device(device)
183
+
184
+ aknob: dashio.Knob = device.get_control(dashio.ControlName.KNOB, "aKNB")
185
+ first_dial_control: dashio.Dial = device.get_control(dashio.ControlName.DIAL, "FirstDial")
186
+
187
+ def knob_event_handler(msg):
188
+ aknob.knob_dial_value = float(msg[3])
189
+ first_dial_control.dial_value = float(msg[3])
190
+
191
+ aknob.add_receive_message_callback(knob_event_handler)
192
+
193
+ while True:
194
+ time.sleep(1)
195
+ ```
196
+
197
+ We've added the cfg64 string. Then decoded it with *dashio.decode_cfg64(cfg64)*. This function returns a dictionary that we can pass into Device so that it can to instantiate and add the controls.
dashio-3.3.2/README.md ADDED
@@ -0,0 +1,181 @@
1
+ # DashIO
2
+
3
+ ![Tests](https://github.com/dashio-connect/python-dashio/actions/workflows/tests.yml/badge.svg)
4
+
5
+ [**DashIO**](http://dashio.io) - It is a quick effortless way to connect your IoT device to your phone, tablet or iPad using the free **Dash** app. It allows easy setup of controls such as Dials, Text Boxes, Charts, Graphs, Notifications..., from your IoT device. You can define the look and layout of the controls on your phone from your IoT device. There are three methods to connect to your phone; Bluetooth Low Energy (BLE), TCP or MQTT.
6
+
7
+ ## Getting Started
8
+
9
+ For the big picture on **DashIO**, take a look at our website: <a href="https://dashio.io">dashio.io</a>
10
+
11
+ ## Documentation
12
+
13
+ For all documentation and software guides: <a href="https://dashio.io/documents">dashio.io/documents</a>
14
+
15
+ For the **DashIO** Python guide: <a href="https://dashio.io/guide-python">dashio.io/guide-python</a>
16
+
17
+ For the **DashIO** Python library: <a href="https://dashio.io/python-library/">dashio.io/python-library</a>
18
+
19
+ ## Examples
20
+
21
+ There are plenty of examples in the github repository under the Examples directory.
22
+
23
+ ## Dash IoT Application
24
+
25
+ The **Dash** app is free and available for both Apple and Android devices. Use it to create beautiful and powerful user interfaces to you IoT devices.
26
+
27
+ Dashio Phone | Dashio Tablet
28
+ :-------------------------:|:-------------------------:
29
+ <img src="https://dashio.io/wp-content/uploads/2020/11/IMG_4154.jpeg" width="150" /> | <img src="https://dashio.io/wp-content/uploads/2020/12/IMG_4203.jpeg" width="450" />
30
+
31
+ ## Requirements
32
+
33
+ * python3.6 and above
34
+ * paho-mqtt
35
+ * pyzmq
36
+ * python-dateutil
37
+ * zeroconf
38
+ * shortuuid
39
+
40
+ ## Install
41
+
42
+ `pip3 install dashio`
43
+
44
+ Or
45
+
46
+ ```sh
47
+ git clone https://github.com/dashio-connect/python-dashio.git
48
+ cd python-dashio
49
+ pip3 install .
50
+ ```
51
+
52
+ ## A Quick Guide
53
+
54
+ This guide covers the **DashIO** python library. For information on the [***Dash***](https://dashio.io/dashboard) phone app please visit the website.
55
+
56
+ ### Basics
57
+
58
+ So what is **DashIO**? It is a quick effortless way to connect your IoT device to your phone. It allows easy setup of controls such as Dials, Text Boxes, Maps, Graphs, Notifications..., from your Device. You can define the look and layout of the controls on your phone from your IoT device. There are three methods to connect to your phone tcp, mqtt, dash, and BLE. What's Dash then? Dash is a mqtt server with extra bits added in to allow you to send notifications, share your devices, and save your settings from your phone via the **Dash** app.
59
+
60
+ Show me some code.
61
+
62
+ ```python
63
+ # Examples/ex01.py
64
+ import dashio
65
+ import random
66
+ import time
67
+
68
+ device = dashio.Device("aDeviceType", "aDeviceID", "aDeviceName")
69
+ tcp_con = dashio.TCPConnection()
70
+ tcp_con.add_device(device)
71
+ first_dial_control = dashio.Dial("FirstDial")
72
+ device.add_control(first_dial_control)
73
+
74
+ while True:
75
+ first_dial_control.dial_value = random.random() * 100
76
+ time.sleep(5)
77
+ ```
78
+
79
+ This is about the fewest lines of code to get talking to the app. There is a lot happening under the hood to make this work. After the import we create a device with three attributes:
80
+
81
+ * "aDeviceType": a common name device_type for all IoT devices using this code which is used for device discovery
82
+ * "aDeviceID": a device_ID to uniquely identify this device, preferably a UUID.
83
+ * "aDeviceName": The name of this device, which can be changed at any time.
84
+
85
+ These attributes describe the device to the app and allow you to distinguish one of your devices from another.
86
+
87
+ The next two lines create a TCP connection and then add the device to the connection. This device is discoverable by the Dash app. You can also discover your IoT device using a third party Bonjour/Zeroconf discovery tool. The mDNS service will be "DashIO.tcp."
88
+
89
+ Though this device is discoverable by the app it would be nice to have the DashIO app automatically setup a new DeviceView and place your control on the new DeviceView. To do that we need to add a few more lines of code:
90
+
91
+ ```python
92
+ # Examples/ex02.py
93
+ import dashio
94
+ import random
95
+ import time
96
+
97
+ device = dashio.Device("aDeviceType", "aDeviceID", "aDeviceName")
98
+ tcp_con = dashio.TCPConnection()
99
+ tcp_con.add_device(device)
100
+ first_dial_control = dashio.Dial("FirstDial", control_position=dashio.ControlPosition(0.24, 0.36, 0.54, 0.26))
101
+ device.add_control(first_dial_control)
102
+
103
+ dv_dial = dashio.DeviceView("aDeviceViewID", "A Dial")
104
+ dv_dial.add_control(first_dial_control)
105
+ device.add_control(dv_dial)
106
+
107
+ while True:
108
+ first_dial_control.dial_value = random.random() * 100
109
+ time.sleep(5)
110
+ ```
111
+
112
+ First we altered the instantiation of a Dial by including a control_position. This allows us to place the control at a set location. The added lines instantiated a DeviceView control, which we than added the dial control. Finally we added the DeviceView to the device.
113
+
114
+ The next piece of the puzzle to consider is how do we get data from the DashIO app? Lets add a Knob and connect it to the Dial:
115
+
116
+ ```python
117
+ # Examples/ex03.py
118
+ import dashio
119
+ import time
120
+
121
+ device = dashio.Device("aDeviceType", "aDeviceID", "aDeviceName")
122
+ tcp_con = dashio.TCPConnection()
123
+ tcp_con.add_device(device)
124
+ first_dial_control = dashio.Dial("FirstDial", control_position=dashio.ControlPosition(0.24, 0.36, 0.54, 0.26))
125
+ device.add_control(first_dial_control)
126
+
127
+ dv = dashio.DeviceView("aDeviceViewID", "A Dial")
128
+ dv.add_control(first_dial_control)
129
+ device.add_control(dv)
130
+
131
+ def knob_event_handler(msg):
132
+ first_dial_control.dial_value = float(msg[3])
133
+
134
+ aknob = dashio.Knob("aKNB", control_position=dashio.ControlPosition(0.24, 0.14, 0.54, 0.26))
135
+ aknob.add_receive_message_callback += knob_event_handler
136
+ dv.add_control(aknob)
137
+ device.add_control(aknob)
138
+
139
+ while True:
140
+ time.sleep(1)
141
+ ```
142
+
143
+ First we added a function that sets the dial value. Next we added a Knob control and added our new function to be called when it receives data from the DashIO app. We also add it to the DeviceView and to the device. Now when the knob in the DashIO app is moved the dial is set to the same value.
144
+
145
+ ### Using the Config64
146
+
147
+ The **Dash** app can generate a CFG64 text string that defines the controls, the controls layout, and device parameters for the Device. The CFG64 string can be used in a number of ways. If we run the example above and using the **Dash** app to export a layout we can use the layout to setup the device and controls.
148
+
149
+ ```python
150
+ # Examples/ex04.py
151
+ import dashio
152
+ import time
153
+
154
+ cfg64 = "pVNdr5pAEP0rN/tMjHCrbXnjQ60RxQD1Nmn6wIVVN8IuXZar1vjfOwuLeNWmTfo2OztzZnLmnBPybA+Z339oaLbwbYhOqBTHDCMT"\
155
+ "LfxgbnlIQwmjgrNs6kIyni1sSJWYpj7Njj4NcIbjEuoFr7CG8viATL3f11ARc0xF0+TiN5LgFcF7eGuI43QVZxU0fRxoSBBRz7Oe"\
156
+ "ZpS9wvcWk81WBLEgDJn9njFUNUtWEshRqLX9KPLncpEt288Jncux6zgrYYVjW3dB0D9oaAfYDssYh+4Ap9Cakjgbsyxj+7Ie3PbL"\
157
+ "fFtpyy01tCep2F7gBgB3uBtiQDYnsFz/DGyGnhs0vEajb5GKnCUyT6hgXCBzMBwASaSw0pTjsoRZ+mejpw8/9fSebvTRWUPuVEHM"\
158
+ "rWUTeP5EZUaLr000CZZfmshauU0Qek6kOh1PBe5q9fLuurYVTh15XMEzYG8MNw7JL/gxYK0NJylQUOUUFjMMSTNcs8m0l6ZVfinR"\
159
+ "b0Ryc285w2Y8xbzl9WVLBH4Kc7bD7f9uQ9OO9jjZqY+/tEQ8pmWtteQI3MtF3mN08nLhsKo1kkmbHR4NbP/ukCUrAagFmc/GVWlH"\
160
+ "nQ5KJUDEIs7lxPBnBd1IysGdWl5Nf8FxQspaxIDYHmM5Hd34bEx4KdTC/+UphfHAU7X+SXYhuHHFH512b6tnACkYoaK7q/ILaOMV"\
161
+ "8ysUbzSOHrv1X61VUSKkS9C1y6JO/XYULdpoouzijCfScGnNVIhFVQAAheNoe7ImmkiKZteOSqXl9SbAbxCez78B"
162
+
163
+ config_dict = dashio.decode_cfg64(cfg64)
164
+ device = dashio.Device("aDeviceType", "aDeviceID", "aDeviceName", cfg_dict=config_dict)
165
+ tcp_con = dashio.TCPConnection()
166
+ tcp_con.add_device(device)
167
+
168
+ aknob: dashio.Knob = device.get_control(dashio.ControlName.KNOB, "aKNB")
169
+ first_dial_control: dashio.Dial = device.get_control(dashio.ControlName.DIAL, "FirstDial")
170
+
171
+ def knob_event_handler(msg):
172
+ aknob.knob_dial_value = float(msg[3])
173
+ first_dial_control.dial_value = float(msg[3])
174
+
175
+ aknob.add_receive_message_callback(knob_event_handler)
176
+
177
+ while True:
178
+ time.sleep(1)
179
+ ```
180
+
181
+ We've added the cfg64 string. Then decoded it with *dashio.decode_cfg64(cfg64)*. This function returns a dictionary that we can pass into Device so that it can to instantiate and add the controls.
@@ -29,11 +29,14 @@ from .enums import Color, ChartLineType, ChartXAxisLabelsStyle, TitlePosition
29
29
  class ChartLine:
30
30
  """ChartLine class
31
31
  """
32
- def __init__(self, name="", line_type=ChartLineType.LINE, color=Color.BLACK):
32
+ def __init__(self, name="", line_type=ChartLineType.LINE, color=Color.BLACK, right_axis=False):
33
33
  self.name = name.translate(BAD_CHARS)
34
34
  self.line_type = line_type
35
35
  self.color = color
36
36
  self.data = []
37
+ self.axis_side = 'left'
38
+ if right_axis:
39
+ self.axis_side = 'right'
37
40
 
38
41
  def get_line_data(self):
39
42
  """Returns the line data formated for the iotdashboard app
@@ -43,7 +46,7 @@ class ChartLine:
43
46
  str
44
47
  The formatted line data
45
48
  """
46
- data_str = f"\t{self.name}\t{self.line_type.value}\t{self.color.value}\t"
49
+ data_str = f"\t{self.name}\t{self.line_type.value}\t{self.color.value}\t{self.axis_side}\t"
47
50
  data_str += "\t".join(map(str, self.data))
48
51
  data_str += "\n"
49
52
  return data_str
@@ -65,6 +68,9 @@ class ChartConfig(ControlConfig):
65
68
  y_axis_min: float,
66
69
  y_axis_max: float,
67
70
  y_axis_num_bars: int,
71
+ y_axis_label_rt: str,
72
+ y_axis_min_rt: float,
73
+ y_axis_max_rt: float,
68
74
  control_position: ControlPosition,
69
75
  ) -> None:
70
76
  super().__init__(control_id, title, control_position, title_position)
@@ -77,6 +83,9 @@ class ChartConfig(ControlConfig):
77
83
  self.cfg["yAxisMin"] = y_axis_min
78
84
  self.cfg["yAxisMax"] = y_axis_max
79
85
  self.cfg["yAxisNumBars"] = y_axis_num_bars
86
+ self.cfg["yAxisLabelRt"] = y_axis_label_rt.translate(BAD_CHARS)
87
+ self.cfg["yAxisMinRt"] = y_axis_min_rt
88
+ self.cfg["yAxisMaxRt"] = y_axis_max_rt
80
89
 
81
90
  @classmethod
82
91
  def from_dict(cls, cfg_dict: dict):
@@ -104,6 +113,9 @@ class ChartConfig(ControlConfig):
104
113
  cfg_dict["yAxisMin"],
105
114
  cfg_dict["yAxisMax"],
106
115
  cfg_dict["yAxisNumBars"],
116
+ cfg_dict["yAxisLabelRt"],
117
+ cfg_dict["yAxisMinRt"],
118
+ cfg_dict["yAxisMaxRt"],
107
119
  ControlPosition(cfg_dict["xPositionRatio"], cfg_dict["yPositionRatio"], cfg_dict["widthRatio"], cfg_dict["heightRatio"])
108
120
  )
109
121
  tmp_cls.parent_id = cfg_dict["parentID"]
@@ -138,8 +150,11 @@ class Chart(Control):
138
150
  x_axis_labels_style=ChartXAxisLabelsStyle.ON,
139
151
  y_axis_label="",
140
152
  y_axis_min=0.0,
141
- y_axis_max=100.0,
153
+ y_axis_max=1000.0,
142
154
  y_axis_num_bars=5,
155
+ y_axis_label_rt="",
156
+ y_axis_min_rt=0.0,
157
+ y_axis_max_rt=1000.0,
143
158
  control_position=None,
144
159
  ):
145
160
  """A Chart Control
@@ -188,6 +203,9 @@ class Chart(Control):
188
203
  y_axis_min,
189
204
  y_axis_max,
190
205
  y_axis_num_bars,
206
+ y_axis_label_rt,
207
+ y_axis_min_rt,
208
+ y_axis_max_rt,
191
209
  control_position
192
210
  )
193
211
  )
@@ -198,6 +216,8 @@ class Chart(Control):
198
216
  self._y_axis_min = y_axis_min
199
217
  self._y_axis_max = y_axis_max
200
218
  self._y_axis_num_bars = y_axis_num_bars
219
+ self._y_axis_min_rt = y_axis_min_rt
220
+ self._y_axis_max_rt = y_axis_max_rt
201
221
 
202
222
  @property
203
223
  def x_axis_min(self):
@@ -224,6 +244,16 @@ class Chart(Control):
224
244
  """Returns the Y axis maximum value"""
225
245
  return self._y_axis_max
226
246
 
247
+ @property
248
+ def y_axis_min_rt(self):
249
+ """Returns the Y axis minimum value right side"""
250
+ return self._y_axis_min_rt
251
+
252
+ @property
253
+ def y_axis_max_rt(self):
254
+ """Returns the Y axis maximum value right side"""
255
+ return self._y_axis_max_rt
256
+
227
257
  @property
228
258
  def y_axis_num_bars(self):
229
259
  """Returns the y axis number of bars"""
@@ -255,6 +285,9 @@ class Chart(Control):
255
285
  cfg_dict["yAxisMin"],
256
286
  cfg_dict["yAxisMax"],
257
287
  cfg_dict["yAxisNumBars"],
288
+ cfg_dict.get("yAxisLabelRt", ''),
289
+ cfg_dict.get("yAxisMinRt", 0.0),
290
+ cfg_dict.get("yAxisMaxRt", 1000.0),
258
291
  ControlPosition(cfg_dict["xPositionRatio"], cfg_dict["yPositionRatio"], cfg_dict["widthRatio"], cfg_dict["heightRatio"])
259
292
  )
260
293
  tmp_cls.parent_id = cfg_dict["parentID"]
@@ -111,7 +111,6 @@ class Icon(Enum):
111
111
  SWITCH = "Switch"
112
112
 
113
113
 
114
-
115
114
  class SoundName(Enum):
116
115
  """Sound names"""
117
116
  DEFAULT = "Default"
@@ -57,7 +57,13 @@ class TimeGraphLine:
57
57
  """A TimeGraphLine for a TimeGraph control
58
58
  """
59
59
  def __init__(
60
- self, name="", line_type=TimeGraphLineType.LINE, color=Color.BLACK, max_data_points=60, break_data=False
60
+ self,
61
+ name: str = "",
62
+ line_type: TimeGraphLineType = TimeGraphLineType.LINE,
63
+ color: Color = Color.BLACK,
64
+ max_data_points: int = 60,
65
+ break_data: bool = False,
66
+ right_axis: bool = False
61
67
  ):
62
68
  """A TimeGraphLine for a TimeGraph control
63
69
 
@@ -79,6 +85,12 @@ class TimeGraphLine:
79
85
  self.color = color
80
86
  self.break_data = break_data
81
87
  self.data = RingBuffer(max_data_points)
88
+ self.axis_side = 'left'
89
+ if right_axis:
90
+ self.axis_side = 'right'
91
+
92
+ def get_line_format(self):
93
+ return f"\t{self.name}\t{self.line_type.value}\t{self.color.value}\t{self.axis_side}\n"
82
94
 
83
95
  def get_line_from_timestamp(self, timestamp: str) -> str:
84
96
  """Converts data from timestamp to a string formatted for the iotdashboard app
@@ -88,7 +100,8 @@ class TimeGraphLine:
88
100
  str
89
101
  Formatted line data
90
102
  """
91
- data_str = f"\t{self.name}\t{self.line_type.value}\t{self.color.value}"
103
+ data_str = f"\t{self.name}\t{self.line_type.value}\t{self.color.value}\t{self.axis_side}"
104
+
92
105
  try:
93
106
  d_stamp = dateutil.parser.isoparse(timestamp)
94
107
  except ValueError:
@@ -144,6 +157,9 @@ class TimeGraphConfig(ControlConfig):
144
157
  y_axis_min: float,
145
158
  y_axis_max: float,
146
159
  y_axis_num_bars: int,
160
+ y_axis_label_rt: str,
161
+ y_axis_min_rt: float,
162
+ y_axis_max_rt: float,
147
163
  control_position: ControlPosition
148
164
  ) -> None:
149
165
  super().__init__(control_id, title, control_position, title_position)
@@ -151,6 +167,9 @@ class TimeGraphConfig(ControlConfig):
151
167
  self.cfg["yAxisMin"] = y_axis_min
152
168
  self.cfg["yAxisMax"] = y_axis_max
153
169
  self.cfg["yAxisNumBars"] = y_axis_num_bars
170
+ self.cfg["yAxisLabelRt"] = y_axis_label_rt.translate(BAD_CHARS)
171
+ self.cfg["yAxisMinRt"] = y_axis_min_rt
172
+ self.cfg["yAxisMaxRt"] = y_axis_max_rt
154
173
 
155
174
  @classmethod
156
175
  def from_dict(cls, cfg_dict: dict):
@@ -173,6 +192,9 @@ class TimeGraphConfig(ControlConfig):
173
192
  cfg_dict["yAxisMin"],
174
193
  cfg_dict["yAxisMax"],
175
194
  cfg_dict["yAxisNumBars"],
195
+ cfg_dict["yAxisLabelRt"],
196
+ cfg_dict["yAxisMinRt"],
197
+ cfg_dict["yAxisMaxRt"],
176
198
  ControlPosition(cfg_dict["xPositionRatio"], cfg_dict["yPositionRatio"], cfg_dict["widthRatio"], cfg_dict["heightRatio"])
177
199
  )
178
200
  tmp_cls.parent_id = cfg_dict["parentID"]
@@ -190,8 +212,11 @@ class TimeGraph(Control):
190
212
  title_position=TitlePosition.BOTTOM,
191
213
  y_axis_label="Y axis",
192
214
  y_axis_min=0.0,
193
- y_axis_max=100.0,
215
+ y_axis_max=1000.0,
194
216
  y_axis_num_bars=5,
217
+ y_axis_label_rt='',
218
+ y_axis_min_rt=0.0,
219
+ y_axis_max_rt=1000.0,
195
220
  control_position=None,
196
221
  ):
197
222
  """A Timegraph control
@@ -225,6 +250,9 @@ class TimeGraph(Control):
225
250
  y_axis_min,
226
251
  y_axis_max,
227
252
  y_axis_num_bars,
253
+ y_axis_label_rt,
254
+ y_axis_min_rt,
255
+ y_axis_max_rt,
228
256
  control_position
229
257
  )
230
258
  )
@@ -233,6 +261,8 @@ class TimeGraph(Control):
233
261
  self._y_axis_min = y_axis_min
234
262
  self._y_axis_max = y_axis_max
235
263
  self._y_axis_num_bars = y_axis_num_bars
264
+ self._y_axis_min_rt = y_axis_min_rt
265
+ self._y_axis_max_rt = y_axis_max_rt
236
266
 
237
267
  self.line_dict = {}
238
268
 
@@ -246,6 +276,16 @@ class TimeGraph(Control):
246
276
  """Returns the Y axis maximum value"""
247
277
  return self._y_axis_max
248
278
 
279
+ @property
280
+ def y_axis_min_rt(self):
281
+ """Returns the Y axis minimum value"""
282
+ return self._y_axis_min_rt
283
+
284
+ @property
285
+ def y_axis_max_rt(self):
286
+ """Returns the Y axis maximum value"""
287
+ return self._y_axis_max_rt
288
+
249
289
  @property
250
290
  def y_axis_num_bars(self):
251
291
  """Returns the y axis number of bars"""
@@ -272,11 +312,22 @@ class TimeGraph(Control):
272
312
  cfg_dict["yAxisMin"],
273
313
  cfg_dict["yAxisMax"],
274
314
  cfg_dict["yAxisNumBars"],
315
+ cfg_dict.get("yAxisLabelRt", ''),
316
+ cfg_dict.get("yAxisMinRt", 0.0),
317
+ cfg_dict.get("yAxisMaxRt", 1000.0),
275
318
  ControlPosition(cfg_dict["xPositionRatio"], cfg_dict["yPositionRatio"], cfg_dict["widthRatio"], cfg_dict["heightRatio"])
276
319
  )
277
320
  tmp_cls.parent_id = cfg_dict["parentID"]
278
321
  return tmp_cls
279
322
 
323
+ def get_state(self):
324
+ state_str = ""
325
+ for key, line in self.line_dict.items():
326
+ line_format = line.get_line_format()
327
+ if line_format:
328
+ state_str += self._control_hdr_str + "BRDCST\t" + key + line_format
329
+ return state_str
330
+
280
331
  def add_line(self, line_id: str, gline: TimeGraphLine):
281
332
  """Add a line to the TimeGraph
282
333