Skip to content

Commit 344199f

Browse files
authored
Merge pull request #31 from VigneshVSV/main
release v0.2.2
2 parents 645d614 + 0577da1 commit 344199f

21 files changed

+204
-185
lines changed

.github/workflows/test.yml renamed to .github/workflows/test-dev.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Python Unit Tests
1+
name: Unit Tests For Development
22

33
on:
44
workflow_dispatch:

.github/workflows/test-release.yml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
name: Unit Tests With TestPyPI
2+
3+
on:
4+
workflow_dispatch:
5+
pull_request:
6+
branches:
7+
- release
8+
9+
10+
jobs:
11+
test:
12+
runs-on: ubuntu-latest
13+
steps:
14+
- name: Checkout code
15+
uses: actions/checkout@v4
16+
17+
- name: Set up Python
18+
uses: actions/setup-python@v3
19+
with:
20+
python-version: 3.11
21+
22+
- name: Install dependencies
23+
run: |
24+
pip install -r tests/requirements.txt
25+
pip install jsonschema
26+
pip install -i https://test.pypi.org/simple/ hololinked
27+
28+
- name: Run unit tests to verify if the release to TestPyPI is working
29+
run: |
30+
python -m unittest discover -s tests -p 'test_*.py'
31+
32+
33+

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1010
### Security
1111
- cookie auth & its specification in TD
1212

13+
## [v0.2.2] - 2024-08-09
14+
15+
- thing control panel works better with the server side and support observable properties
16+
- `ObjectProxy` client API has been improved to resemble WoT operations better, for examplem `get_property` is now
17+
called `read_property`, `set_properties` is now called `write_multiple_properties`.
18+
- `ObjectProxy` client reliability for poorly written server side actions improved
19+
1320
## [v0.2.1] - 2024-07-21
1421

1522
### Added

CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ Otherwise, I will then take care of the issue as soon as possible.
4747
Developers are always welcome to contribute to the code base. If you want to tackle any issues, un-existing features, let me know (at my email), I can create some open issues and features which I was never able to solve or did not have the time. You can also suggest what else can be contributed functionally or conceptually or also simply code-refactoring. The lack of issues or features in the [Issues](https://github.com/VigneshVSV/hololinked/issues) section of github does not mean the project is considered feature complete or I dont have ideas what to do next. On the contrary, there is tons of work to do.
4848

4949
There are also repositories which can use your skills:
50-
- An [admin client](https://github.com/VigneshVSV/hololinked-portal) in react
50+
- An [admin client](https://github.com/VigneshVSV/thing-control-panel) in react
5151
- [Documentation](https://github.com/VigneshVSV/hololinked-docs) in sphinx which needs significant improvement in How-To's, beginner level docs which may teach people concepts of data acquisition or IoT, Docstring or API documentation of this repository itself
5252
- [Examples](https://github.com/VigneshVSV/hololinked-examples) in nodeJS, Dashboard/PyQt GUIs or server implementations using this package. Hardware implementations of unexisting examples are also welcome, I can open a directory where people can search for code based on hardware and just download your code.
5353

README.md

Lines changed: 33 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
# hololinked - Pythonic Supervisory Control & Data Acquisition / Internet of Things
1+
# hololinked - Pythonic Object-Oriented Supervisory Control & Data Acquisition / Internet of Things
22

33
### Description
44

5-
For beginners - `hololinked` is a server side pythonic package suited for instrumentation control and data acquisition over network, especially with HTTP. If you have a requirement to control and capture data from your hardware/instrumentation, show the data in a browser/dashboard, provide a GUI or run automated scripts, `hololinked` can help. Even for isolated applications or a small lab setup without networking concepts, one can still separate the concerns of the tools that interact with the hardware & the hardware itself.
6-
<br/> <br/>
7-
For those familiar with RPC & web development - This package is an implementation of a ZeroMQ-based Object Oriented RPC with customizable HTTP end-points. A dual transport in both ZMQ and HTTP is provided to maximize flexibility in data type, serialization and speed, although HTTP is preferred for networked applications. If one is looking for an object oriented approach towards creating components within a control or data acquisition system, or an IoT device, one may consider this package.
5+
`hololinked` is a server side pythonic tool suited for instrumentation control and data acquisition over network, especially with HTTP. If you have a requirement to control and capture data from your hardware/instrumentation, show the data in a browser/dashboard, provide a GUI or run automated scripts, `hololinked` can help. Even for isolated applications or a small lab setup without networking concepts, one can still separate the concerns of the tools that interact with the hardware & the hardware itself.
86

9-
[![Documentation Status](https://readthedocs.org/projects/hololinked/badge/?version=latest)](https://hololinked.readthedocs.io/en/latest/?badge=latest) [![PyPI](https://img.shields.io/pypi/v/hololinked?label=pypi%20package)](https://pypi.org/project/hololinked/) [![PyPI - Downloads](https://img.shields.io/pypi/dm/hololinked)](https://pypistats.org/packages/hololinked) [![codecov](https://codecov.io/gh/VigneshVSV/hololinked/graph/badge.svg?token=JF1928KTFE)](https://codecov.io/gh/VigneshVSV/hololinked)
7+
[![Documentation Status](https://readthedocs.org/projects/hololinked/badge/?version=latest)](https://hololinked.readthedocs.io/en/latest/?badge=latest) [![PyPI](https://img.shields.io/pypi/v/hololinked?label=pypi%20package)](https://pypi.org/project/hololinked/) [![PyPI - Downloads](https://img.shields.io/pypi/dm/hololinked)](https://pypistats.org/packages/hololinked) [![codecov](https://codecov.io/gh/VigneshVSV/hololinked/graph/badge.svg?token=JF1928KTFE)](https://codecov.io/gh/VigneshVSV/hololinked)
8+
<br>
9+
[![email](https://img.shields.io/badge/email%20me-brown)](mailto:vignesh.vaidyanathan@hololinked.dev) [![find me on discord](https://img.shields.io/badge/find_me_on_discord-brown)](https://discord.com/users/1178428338746966066)
1010

1111
### To Install
1212

@@ -19,16 +19,14 @@ Or, clone the repository (develop branch for latest codebase) and install `pip i
1919
`hololinked` is compatible with the [Web of Things](https://www.w3.org/WoT/) recommended pattern for developing hardware/instrumentation control software.
2020
Each device or thing can be controlled systematically when their design in software is segregated into properties, actions and events. In object oriented terms:
2121
- the hardware is (generally) represented by a class
22-
- properties are validated get-set attributes of the class which may be used to model hardware settings, hold captured/computed data or generic network accessible quantities
22+
- properties are validated get-set attributes of the class which may be used to model settings, hold captured/computed data or generic network accessible quantities
2323
- actions are methods which issue commands like connect/disconnect, execute a control routine, start/stop measurement, or run arbitray python logic
2424
- events can asynchronously communicate/push (arbitrary) data to a client (say, a GUI), like alarm messages, streaming measured quantities etc.
2525

26-
It does not even matter whether you are controlling your hardware locally or remotely, what protocol you use, what is the nature of the client etc.,
27-
one has to provide these three interactions with the hardware. In this package, the base class which enables this classification is the `Thing` class. Any class that inherits the `Thing` class
28-
can instantiate properties, actions and events which
29-
become visible to a client in this segragated manner. For example, consider an optical spectrometer, the following code is possible:
26+
In this package, the base class which enables this classification is the `Thing` class. Any class that inherits the `Thing` class
27+
can instantiate properties, actions and events which become visible to a client in this segragated manner. For example, consider an optical spectrometer, the following code is possible:
3028

31-
> This is a fairly mid-level intro, if you are beginner, for another variant check [How-To](https://hololinked.readthedocs.io/en/latest/howto/index.html)
29+
> This is a fairly mid-level intro focussed on HTTP. If you are beginner or looking for ZMQ which can be used with no networking knowledge, check [How-To](https://hololinked.readthedocs.io/en/latest/howto/index.html)
3230
3331
#### Import Statements
3432

@@ -64,8 +62,8 @@ class OceanOpticsSpectrometer(Thing):
6462
serial_number = String(default=None, allow_None=True, URL_path='/serial-number',
6563
doc="serial number of the spectrometer to connect/or connected",
6664
http_method=("GET", "PUT"))
67-
# GET and PUT is default for reading and writing the property respectively.
68-
# Use other HTTP methods if necessary.
65+
# GET and PUT is default for reading and writing the property respectively.
66+
# So you can leave it out, especially if you are going to use ZMQ and dont understand HTTP
6967

7068
integration_time = Number(default=1000, bounds=(0.001, None), crop_to_bounds=True,
7169
URL_path='/integration-time',
@@ -81,10 +79,9 @@ class OceanOpticsSpectrometer(Thing):
8179
```
8280

8381
In non-expert terms, properties look like class attributes however their data containers are instantiated at object instance level by default.
84-
For example, the `integratime_time` property defined above as `Number`, whenever set/written, will be validated as a float or int, cropped to bounds and assigned as an attribute to each instance of the `OceanOpticsSpectrometer` class with an internally generated name. It is not necessary to know this internally generated name as the property value can be accessed again in any python logic, say, `print(self.integration_time)`.
82+
For example, the `integration_time` property defined above as `Number`, whenever set/written, will be validated as a float or int, cropped to bounds and assigned as an attribute to each instance of the `OceanOpticsSpectrometer` class with an internally generated name. It is not necessary to know this internally generated name as the property value can be accessed again in any python logic, say, `print(self.integration_time)`.
8583

8684
To overload the get-set (or read-write) of properties, one may do the following:
87-
8885
```python
8986
class OceanOpticsSpectrometer(Thing):
9087

@@ -132,8 +129,7 @@ Those familiar with Web of Things (WoT) terminology may note that these properti
132129
```
133130
If you are not familiar with Web of Things or the term "property affordance", consider the above JSON as a description of
134131
what the property represents and how to interact with it from somewhere else. Such a JSON is both human-readable, yet consumable
135-
by a client provider to create a client object to interact with the property in the way the property demands. You, as the developer,
136-
only need to use the client.
132+
by a client provider to create a client object to interact with the property.
137133

138134
The URL path segment `../spectrometer/..` in href field is taken from the `instance_name` which was specified in the `__init__`.
139135
This is a mandatory key word argument to the parent class `Thing` to generate a unique name/id for the instance. One should use URI compatible strings.
@@ -153,6 +149,13 @@ class OceanOpticsSpectrometer(Thing):
153149
self.serial_number = serial_number
154150
self.device = Spectrometer.from_serial_number(self.serial_number)
155151
self._wavelengths = self.device.wavelengths().tolist()
152+
153+
# So you can leave it out, especially if you are going to use ZMQ and dont understand HTTP
154+
@action()
155+
def disconnect(self):
156+
"""disconnect from the spectrometer"""
157+
self.device.close()
158+
156159
```
157160

158161
Methods that are neither decorated with action decorator nor acting as getters-setters of properties remain as plain python methods and are **not** accessible on the network.
@@ -266,6 +269,8 @@ what the event represents and how to subscribe to it) with subprotocol SSE (HTTP
266269
```
267270
> data schema ("data" field above which describes the event payload) are optional and discussed later
268271
272+
Events follow a pub-sub model with '1 publisher to N subscribers' per `Event` object, both through ZMQ and HTTP SSE.
273+
269274
Although the code is the very familiar & age-old RPC server style, one can directly specify HTTP methods and URL path for each property, action and event. A configurable HTTP Server is already available (from `hololinked.server.HTTPServer`) which redirects HTTP requests to the object according to the specified HTTP API on the properties, actions and events. To plug in a HTTP server:
270275

271276
```python
@@ -284,14 +289,17 @@ if __name__ == '__main__':
284289
log_level=logging.DEBUG
285290
)
286291
O.run_with_http_server(ssl_context=ssl_context)
292+
# or O.run(zmq_protocols='IPC') - interprocess communication and no HTTP
293+
# or O.run(zmq_protocols=['IPC', 'TCP'], tcp_socket_address='tcp://*:9999')
294+
# both interprocess communication & TCP, no HTTP
287295
```
288296

289297
Here one can see the use of `instance_name` and why it turns up in the URL path. See the detailed example of the above code [here](https://gitlab.com/hololinked-examples/oceanoptics-spectrometer/-/blob/simple/oceanoptics_spectrometer/device.py?ref_type=heads).
290298

291-
##### NOTE - The package is under active development. Contributors welcome, please check CONTRIBUTING.md.
299+
##### NOTE - The package is under active development. Contributors welcome, please check CONTRIBUTING.md and the open issues. Some issues can also be independently dealt without much knowledge of this package.
292300

293301
- [example repository](https://github.com/VigneshVSV/hololinked-examples) - detailed examples for both clients and servers
294-
- [helper GUI](https://github.com/VigneshVSV/hololinked-portal) - view & interact with your object's methods, properties and events.
302+
- [helper GUI](https://github.com/VigneshVSV/thing-control-panel) - view & interact with your object's actions, properties and events.
295303

296304
See a list of currently supported possibilities while using this package [below](#currently-supported).
297305

@@ -306,24 +314,25 @@ One may use the HTTP API according to one's beliefs (including letting the packa
306314
- auto-generate Thing Description for Web of Things applications.
307315
- use serializer of your choice (except for HTTP) - MessagePack, JSON, pickle etc. & extend serialization to suit your requirement. HTTP Server will support only JSON serializer to maintain compatibility with node-wot. Default is JSON serializer based on msgspec.
308316
- asyncio compatible - async RPC server event-loop and async HTTP Server - write methods in async
309-
- choose from multiple ZeroMQ transport methods. Some of the possibilities one can achieve by choosing ZMQ transport methods:
317+
- choose from multiple ZeroMQ transport methods which offers some possibilities like the following without changing the code:
310318
- run HTTP Server & python object in separate processes or the same process
311319
- serve multiple objects with the same HTTP server
312320
- run direct ZMQ-TCP server without HTTP details
313321
- expose only a dashboard or web page on the network without exposing the hardware itself
314-
322+
315323
Again, please check examples or the code for explanations. Documentation is being activety improved.
316324

317325
### Currently being worked
318326

319327
- improving accuracy of Thing Descriptions
320328
- cookie credentials for authentication - as a workaround until credentials are supported, use `allowed_clients` argument on HTTP server which restricts access based on remote IP supplied with the HTTP headers.
321329

330+
### Internals
331+
332+
This package is an implementation of a ZeroMQ-based Object Oriented RPC with customizable HTTP end-points. A dual transport in both ZMQ and HTTP is provided to maximize flexibility in data type, serialization and speed, although HTTP is preferred for networked applications. If one is looking for an object oriented approach towards creating components within a control or data acquisition system, or an IoT device, one may consider this package.
333+
322334
### Some Day In Future
323335

324336
- mongo DB support for DB operations
325337
- HTTP 2.0
326338

327-
### Contact
328-
329-
Contributors welcome for all my projects related to hololinked including web apps. Please write to my contact email available at my [website](https://hololinked.dev).

doc

Submodule doc updated from 68e1be2 to a064864

examples

hololinked/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "0.2.1"
1+
__version__ = "0.2.2"

0 commit comments

Comments
 (0)