Skip to content

Commit 979c357

Browse files
author
Rene Schallner
committed
initial commit
1 parent 884ed99 commit 979c357

11 files changed

Lines changed: 1408 additions & 0 deletions

File tree

README.md

Lines changed: 337 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,337 @@
1+
# NIM Technology Lab Sensor Sync API
2+
3+
<!-- vim-markdown-toc GFM -->
4+
5+
* [0. Introduction](#0-introduction)
6+
* [1. Configuring the device](#1-configuring-the-device)
7+
* [1.1 Restoring the default configuration](#11-restoring-the-default-configuration)
8+
* [2. APIs](#2-apis)
9+
* [2.1 Python API](#21-python-api)
10+
* [2.1.1 Prerequisites](#211-prerequisites)
11+
* [2.1.1.1 The pipenv way](#2111-the-pipenv-way)
12+
* [2.1.1.2 Without pipenv](#2112-without-pipenv)
13+
* [2.1.2 Examples](#212-examples)
14+
* [2.2 Python API (type-checked)](#22-python-api-type-checked)
15+
* [2.2.1 Prerequisites](#221-prerequisites)
16+
* [2.2.2 Examples](#222-examples)
17+
* [2.3 Javascript API](#23-javascript-api)
18+
* [2.3.1 Examples](#231-examples)
19+
20+
<!-- vim-markdown-toc -->
21+
22+
## 0. Introduction
23+
24+
25+
The NIM Sensor Sync device was designed to enable easy real-time synchronization of sensor data and lab experiment
26+
(online) software. This is necessary since sensor data capturing devices or software and the experiment software can run
27+
on different systems and produce separate data streams. An online experiment might produce a .CSV file or log file on
28+
the web server - whereas the sensor capturing software might run on a proband-facing laptop in the lab, producing a
29+
different CSV file. Synchronizing these two data streams: from the experiment software and from the sensor data
30+
capturing software is essential for correlation of sensor data to events during a lab experiment.
31+
32+
The NIM Sensor Sync provides electrical sensor interfaces that can be controlled over the network via HTTP. Sensor
33+
capturing devices such as a biosignalsplux sensor hub can capture the state of these networked sensor outputs that in
34+
turn are controlled by the experiment software via an easy HTTP API.
35+
36+
Using the networked sensor outputs, the experiment software can send synchronization pulses to the sensor capturing
37+
device. That way, it can place marks in the sensor data - e.g. when a proband started interacting with the experiment
38+
software, pressed a certain button, started watching a video, etc.
39+
40+
One NIM Sensor Sync device provides 8 networked sensor outputs. The following illustration shows an exemplary setup,
41+
where two lab seats are equipped with a laptop and two different sensors each. All sensors are connected to a 6-channel
42+
sensor hub. For synchronization, two inputs of the sensor hub - one for each proband laptop - are connected to the NIM
43+
Sensor Sync's sensor outputs. The Sensor Sync device is connected to the Ethernet network, as are all proband laptops
44+
and the master PC for the experiment administrator. In this scenario, sensor data synchronization "mark" requests can be
45+
sent either by the web server running the experiment backend on the master PC or by the web browsers of the proband
46+
laptops during the experiment.
47+
48+
![](img/overview.png)
49+
50+
## 1. Configuring the device
51+
52+
Use [the configuration tool](./sample.html). You can run it by opening it ([sample.html](sample.html)) in a browser, no
53+
HTTP server required.
54+
55+
This tool allows you to:
56+
57+
- configure a connected device's IP address
58+
- configure a connected device's MAC address
59+
- reboot a connected device -> IP and MAC changes take effect
60+
- read current config (including sensor states)
61+
- change sensor states (outputs)
62+
63+
### 1.1 Restoring the default configuration
64+
The default configuration:
65+
66+
- IP: `192.168.2.49`
67+
- MAC: `CA.FE.EE.CA.FE.ED`
68+
69+
These defaults are restored when you:
70+
- power up the device
71+
- within 5 seconds,
72+
- hold the button for 3 seconds
73+
- _(as an indicator that the default config was restored, the LED light will deactivate)_
74+
- reboot (power cycle) the device
75+
76+
## 2. APIs
77+
78+
## 2.1 Python API
79+
80+
See [python/](python/)
81+
82+
### 2.1.1 Prerequisites
83+
84+
#### 2.1.1.1 The pipenv way
85+
The API supports [pipenv](https://pipenv.pypa.io). Install pipenv by running:
86+
87+
```console
88+
pip install --user pipenv
89+
```
90+
91+
To install dependencies, run:
92+
93+
```console
94+
$ pipenv install
95+
```
96+
97+
Then, to run `ssync.py`, which tests all API functions against a device using the [default
98+
configuration](#11-restoring-the-default-configuration), run the following:
99+
100+
```console
101+
$ pipenv run python ssync.py
102+
```
103+
104+
Please note that instead of prefixing every command with `pipenv run`, you can alternatively also open a pipenv shell:
105+
106+
```console
107+
$ pipenv shell
108+
```
109+
110+
#### 2.1.1.2 Without pipenv
111+
112+
Ensure you are running python 3.8 or above. Then run:
113+
114+
```console
115+
$ pip install requests
116+
```
117+
118+
Then, to run `ssync.py`, which tests all API functions against a device using the [default
119+
configuration](#11-restoring-the-default-configuration), run the following:
120+
121+
```console
122+
$ python ssync.py
123+
```
124+
125+
126+
### 2.1.2 Examples
127+
128+
```python
129+
# import and init
130+
import SensorSync from ssync
131+
s = SensorSync('192.168.2.49')
132+
133+
# or
134+
# s = SensorSync()
135+
# s.ip = '192.168.2.49'
136+
137+
138+
# set and reset sensors
139+
# valid sensor numbers: 1..8
140+
OK, _ = s.activate(1)
141+
OK, _ = s.reset(1)
142+
143+
# optionally, check the returned html when activating/resetting:
144+
OK, _ = s.activate(1, verify=True)
145+
OK, _ = s.reset(1, verify=True)
146+
147+
# request status
148+
OK, status_html = s.status()
149+
150+
# status_html looks like this:
151+
<html>
152+
Version 2.3
153+
IP=192.168.2.49
154+
MAC=DE.AD.BE.EF.FE.ED
155+
SENSORS=0
156+
</html>
157+
158+
# re-configure device:
159+
OK, _ = s.write_ip('192.168.2.49')
160+
OK, _ = s.write_mac('CA.FE.EE.CA.FE.ED')
161+
OK, _ = s.reboot()
162+
```
163+
164+
## 2.2 Python API (type-checked)
165+
166+
### 2.2.1 Prerequisites
167+
168+
Optionally, a type-checked version of the API exists. It lives in
169+
[./python/type_checked_python_3.9_and_above](./python/type_checked_python_3.9_and_above/).
170+
171+
**The type-checked API requires python 3.9 or above!**
172+
173+
Its dependencies are:
174+
- `python3.9` or above
175+
- `requests` : runtime only
176+
- `mypy` : type-checker, development time only
177+
- `types-requests` : development time only
178+
179+
So, if you just want to use the API, you only need to `pip install requests` and you are done.
180+
181+
If you plan to develop and use `mypy` for type-checking, we recommend using [pipenv](https://pipenv.pypa.io). Install
182+
pipenv by running:
183+
184+
```console
185+
pip install --user pipenv
186+
```
187+
188+
To install dependencies, run:
189+
190+
```console
191+
$ pipenv install -d
192+
```
193+
194+
Then, to run `ssync.py`, which tests all API functions against a device using the [default
195+
configuration](#11-restoring-the-default-configuration), run the following:
196+
197+
```console
198+
$ pipenv run python ssync.py
199+
```
200+
201+
To perform a type-check, run:
202+
203+
```console
204+
$ pipenv run mypy .
205+
```
206+
207+
Please note that instead of prefixing every command with `pipenv run`, you can alternatively also open a pipenv shell:
208+
209+
```console
210+
$ pipenv shell
211+
```
212+
213+
### 2.2.2 Examples
214+
215+
```python
216+
# import and init
217+
import SensorSync from ssync
218+
s = SensorSync('192.168.2.49')
219+
220+
# or
221+
# s = SensorSync()
222+
# s.ip = '192.168.2.49'
223+
224+
225+
# set and reset sensors
226+
# valid sensor numbers: 1..8
227+
OK, _ = s.activate(1)
228+
OK, _ = s.reset(1)
229+
230+
# optionally, check the returned html when activating/resetting:
231+
OK, _ = s.activate(1, verify=True)
232+
OK, _ = s.reset(1, verify=True)
233+
234+
# request status
235+
OK, status_html = s.status()
236+
237+
# status_html looks like this:
238+
<html>
239+
Version 2.3
240+
IP=192.168.2.49
241+
MAC=DE.AD.BE.EF.FE.ED
242+
SENSORS=0
243+
</html>
244+
245+
# re-configure device:
246+
OK, _ = s.write_ip('192.168.2.49')
247+
OK, _ = s.write_mac('CA.FE.EE.CA.FE.ED')
248+
OK, _ = s.reboot()
249+
```
250+
251+
## 2.3 Javascript API
252+
253+
See [javascript/](javascript/). A simple demo web page, [ssync-demo.html](javascript/ssync-demo.html), is provided, too.
254+
You can open it directly in the browser, no web server required.
255+
256+
Should your system insist on a web server, there's always:
257+
258+
```console
259+
python3 -m http.server .
260+
```
261+
262+
### 2.3.1 Examples
263+
264+
```javascript
265+
// set IP address to use:
266+
// ------------------------------------------------------------------------
267+
set_ssync_ip(ip_address_as_string);
268+
269+
270+
// activate a sensor:
271+
// ------------------------------------------------------------------------
272+
activate_sensor(sensor_number); // sensor number range: 1..8
273+
274+
275+
// de-activate a sensor:
276+
// ------------------------------------------------------------------------
277+
reset_sensor(sensor_number); // sensor number range: 1..8
278+
279+
280+
// read config:
281+
// ------------------------------------------------------------------------
282+
read_config() // returns a promise, access with .then(...)
283+
284+
read_config().then(data => console.log(data.ip, data.mac, data.sensors))
285+
286+
287+
288+
// return values and error handling
289+
// ------------------------------------------------------------------------
290+
// just activate
291+
activate_sensor(1);
292+
293+
// activate sensor and log result to console
294+
activate_sensor(1).then(result_html => console.log(result_html));
295+
296+
// activate sensor and log result to console, catch and log error
297+
activate_sensor(1)
298+
.then(result_html => console.log(result_html))
299+
.catch(function (err) {
300+
console.log('Fetch Error :-S', err);
301+
});
302+
303+
// NOTE: if you chain multiple calls and want them to be executed in order,
304+
// use the `await` keyword. This only works inside of functions:
305+
306+
async function foo() {
307+
console.log('the following happens in order')
308+
309+
// just activate
310+
await activate_sensor(1);
311+
312+
// activate sensor and log result to console
313+
await activate_sensor(1).then(result_html => console.log(result_html));
314+
315+
// activate sensor and log result to console, catch and log error
316+
await activate_sensor(1)
317+
.then(result_html => console.log(result_html))
318+
.catch(function (err) {
319+
console.log('Fetch Error :-S', err);
320+
});
321+
322+
await read_config().then(data => console.log('\n',
323+
'ip: ' + data.ip, '\n',
324+
'mac: ' + data.mac, '\n',
325+
'sensor states: ', data.sensors, '\n',
326+
data)
327+
);
328+
329+
console.log('finished');
330+
}
331+
332+
// call the function
333+
foo();
334+
335+
// see `ssync-demo.html` for an example for how to use this inside of an HTML file.
336+
```
337+

img/overview.png

75.6 KB
Loading

0 commit comments

Comments
 (0)