HSP

Version 27 (J. Simmons, 06/10/2018 05:32 pm)

1 27 J. Simmons
h1. Holoseat Controller Communications Protocol
2 1 J. Simmons
3 1 J. Simmons
{{>toc}}
4 1 J. Simmons
5 1 J. Simmons
h2. Introduction
6 1 J. Simmons
7 27 J. Simmons
The Holoseat controller has a two layer communication stack.  The lower (private) layer is a custom serial protocol, implemented in JSON messages.  The upper (public) layer is a "Socket.io":https://socket.io/ event/message API wrapping around the serial protocol.  This architecture places the bulk of the responsibility for implementation on the firmware, accessed using the private layer.  The public layer is then only responsible for passing messages in/out of the private API and reporting when the Holoseat is disconnected.
8 1 J. Simmons
9 27 J. Simmons
This page serves to document both layers.  Each event/message will be covered at a conceptual level followed by layer specific information and examples.
10 27 J. Simmons
11 1 J. Simmons
h2. Serial Port Configuration
12 1 J. Simmons
13 2 J. Simmons
|*Field*|*Value*|
14 1 J. Simmons
|Baud Rate|115200|
15 1 J. Simmons
|Data Bits|8|
16 1 J. Simmons
|Parity|None|
17 1 J. Simmons
|Stop Bit|1|
18 2 J. Simmons
19 27 J. Simmons
h2. Controller Events/Messages
20 4 J. Simmons
21 27 J. Simmons
This section covers the events and message that the controller responds to (aka those sent to the controller by clients).
22 1 J. Simmons
23 27 J. Simmons
Note, the various set_* events only broadcast their corresponding client events when they receive data that leads to an actual state change.  So, if the Holoseat is already enabled and set_enabled is called with a value of True, then no state change will occur and in turn the enabled event will not be broadcast to the clients.
24 1 J. Simmons
25 27 J. Simmons
h3. connect (event)
26 1 J. Simmons
27 27 J. Simmons
*Purpose:*  Used to establish client connection
28 1 J. Simmons
29 27 J. Simmons
*Event Specific Inputs*
30 1 J. Simmons
31 27 J. Simmons
* none
32 1 J. Simmons
33 27 J. Simmons
*Response*
34 1 J. Simmons
35 27 J. Simmons
# controller-version message sent to connecting client
36 27 J. Simmons
# enabled event sent to connecting client
37 27 J. Simmons
# cadence event sent to connecting client
38 27 J. Simmons
# configuration event sent to connecting client
39 27 J. Simmons
# resistance event sent to connecting client FUTURE DEVELOPMENT
40 1 J. Simmons
41 27 J. Simmons
h4. Public Layer Details
42 1 J. Simmons
43 27 J. Simmons
*Event Name:* connect
44 27 J. Simmons
*Event Data:* none
45 27 J. Simmons
46 27 J. Simmons
h4. Private Layer Details
47 27 J. Simmons
48 27 J. Simmons
*Serial Message:* @{"event_name":"connect", "client_id":<socket.id>}@
49 27 J. Simmons
50 27 J. Simmons
h3. set_enabled (event)
51 27 J. Simmons
52 27 J. Simmons
*Purpose:*  Used to toggle enabled state
53 27 J. Simmons
54 27 J. Simmons
*Event Specific Inputs*
55 27 J. Simmons
56 27 J. Simmons
* enabled: boolean - new enabled state for the holoseat controller
57 27 J. Simmons
58 27 J. Simmons
*Response*
59 27 J. Simmons
60 27 J. Simmons
# enabled event sent to all clients
61 27 J. Simmons
62 27 J. Simmons
h4. Public Layer Details
63 27 J. Simmons
64 27 J. Simmons
*Event Name:* set_enabled
65 27 J. Simmons
*Event Data:* @{"enabled":<True|False>}@
66 27 J. Simmons
67 27 J. Simmons
h4. Private Layer Details
68 27 J. Simmons
69 27 J. Simmons
*Serial Message:* @{"event_name":"set_enabled", "client_id":<socket.id>, "data":{"enabled":<True|False>}}@
70 27 J. Simmons
71 27 J. Simmons
h3. set_configuration (event)
72 27 J. Simmons
73 27 J. Simmons
*Purpose:* Used to give Holoseat a new configuration (aka tell it how to react to cadences)
74 27 J. Simmons
75 27 J. Simmons
*Event Specific Inputs*
76 27 J. Simmons
77 27 J. Simmons
* configuration: configuration data (see below) or an empty dictionary to reset Holoseat to hardware default configuration (*wasd*)
78 27 J. Simmons
79 27 J. Simmons
*Response*
80 27 J. Simmons
81 27 J. Simmons
# configuration event sent to connecting client
82 27 J. Simmons
83 27 J. Simmons
h4. Configuration Schema
84 27 J. Simmons
85 27 J. Simmons
* name(string): label for the current configuration 
86 27 J. Simmons
* forward = dictionary: how to respond to forward pedaling
87 27 J. Simmons
** hid(string <"keyboard" | "mouse" | "joypad">): what device is being emulated for this direction (v1.0.x will only support keyboard)
88 27 J. Simmons
** responses(array of dictionaries): list of responses keyed off of trigger cadences
89 27 J. Simmons
*** triggerCadence(int): action occurs when current cadence >= triggerCadence; use 0 for at all cadences
90 27 J. Simmons
*** actions(array): set of discrete hid actions to take (e.g. [“shift”, “w”] could indicate pressing the shift+w on keyboard); specifics are device emulation dependent, will be specified in a separate doc; actions are always to hold some hid signal until cadence changes and action is reevaluated (in other words actions cannot be single press/click)
91 27 J. Simmons
* reverse(dictionary): how to respond to reverse pedaling (same structure as forward)
92 27 J. Simmons
93 27 J. Simmons
h5. Hardware defaults in configuration JSON 
94 27 J. Simmons
95 27 J. Simmons
@{"name":"wasd", "forward":{"hid":"keyboard", "responses":[{"triggerCadence":0, "actions":["w"]}]}, "reverse":{"hid":"keyboard", "responses":[{"triggerCadence":0, "actions":["s"]}]}}@
96 27 J. Simmons
97 27 J. Simmons
This string would be hard coded into the firmware and used to initialize the default configuration object.
98 27 J. Simmons
99 27 J. Simmons
h5. The No Op configuration JSON 
100 27 J. Simmons
101 27 J. Simmons
Used by games responding to the cadence stream instead of hid actions.
102 27 J. Simmons
103 27 J. Simmons
@{"name":"noop", "forward":{"hid":"keyboard", "responses":[]}, "reverse":{"hid":"keyboard", "responses":[]}}@
104 27 J. Simmons
105 27 J. Simmons
Note the use of empty arrays for the responses.  This can be used separately for configurations where only one direction makes sense.
106 27 J. Simmons
107 27 J. Simmons
h4. Public Layer Details
108 27 J. Simmons
109 27 J. Simmons
*Event Name:* set_configuration
110 27 J. Simmons
*Event Data:* @{"configuration":<configuration object>}@
111 27 J. Simmons
112 27 J. Simmons
h4. Private Layer Details
113 27 J. Simmons
114 27 J. Simmons
*Serial Message:* @{"event_name":"set_configuration", "client_id":<socket.id>, "data":{"configuration":<configuration object>}}@
115 27 J. Simmons
116 27 J. Simmons
h3. set_resistance (event) FUTURE DEVELOPMENT
117 27 J. Simmons
118 27 J. Simmons
*Purpose:* Manage the resistance level of the execise equipment Holoseat is connected to
119 27 J. Simmons
120 27 J. Simmons
h4. Public Layer Details
121 27 J. Simmons
122 27 J. Simmons
TBD
123 27 J. Simmons
124 27 J. Simmons
h4. Private Layer Details
125 27 J. Simmons
126 27 J. Simmons
TBD
127 27 J. Simmons
128 27 J. Simmons
129 27 J. Simmons
h2. Client Events/Messages
130 27 J. Simmons
131 27 J. Simmons
This section covers the events and message that clients must respond to (aka those sent by the controller to clients).  
132 27 J. Simmons
133 27 J. Simmons
Note, events and messages read from the private layer may leave out the client_id.  No client_id indicate public layer shoud broadcast the event/message to all connects clients (this ia the typcial behavior).  Otherwise, the event/message should be sent only to th specified client.
134 27 J. Simmons
135 27 J. Simmons
h3. enabled (event)
136 27 J. Simmons
137 27 J. Simmons
*Purpose:* Updates clients of enabled state when it changes
138 27 J. Simmons
139 27 J. Simmons
*Event Specific Inputs*
140 27 J. Simmons
141 27 J. Simmons
* state: string indicating state <"enabled" | "disabled" | "disconnected">
142 27 J. Simmons
143 27 J. Simmons
h4. Public Layer Details
144 27 J. Simmons
145 27 J. Simmons
*Event Name:* enabled
146 27 J. Simmons
*Event Data:* @{"state":<"enabled" | "disabled" | "disconnected">}@
147 27 J. Simmons
148 27 J. Simmons
Note, The public layer is the layer which determines if the state is "disconnected". This determination is made every time an event is handled by the public layer.  If Holoseat is disconnectd, this event will be broadcast to all clients regardless of value in the client_id field or the original event received.
149 27 J. Simmons
150 27 J. Simmons
h4. Private Layer Details
151 27 J. Simmons
152 27 J. Simmons
*Serial Message:* @{"event_name":"enabled", "client_id":<socket.id>, "data":{"state":<"enabled" | "disabled">}}@
153 27 J. Simmons
154 27 J. Simmons
h3. cadence (event)
155 27 J. Simmons
156 27 J. Simmons
*Purpose:* Updates clients of cadence when it changes
157 27 J. Simmons
158 27 J. Simmons
*Event Specific Inputs*
159 27 J. Simmons
160 27 J. Simmons
* cadence: integer indicating how fast user is pedalling/stepping
161 27 J. Simmons
162 27 J. Simmons
h4. Public Layer Details
163 27 J. Simmons
164 27 J. Simmons
*Event Name:* cadence
165 27 J. Simmons
*Event Data:* @{"cadence":<current cadence>}@
166 27 J. Simmons
167 27 J. Simmons
h4. Private Layer Details
168 27 J. Simmons
169 27 J. Simmons
*Serial Message:* @{"event_name":"cadence", "client_id":<socket.id>, "data":{"cadence":<current cadence>}}@
170 27 J. Simmons
171 27 J. Simmons
h3. configuration (event)
172 27 J. Simmons
173 27 J. Simmons
*Purpose:* Updates clients of cadence when it changes
174 27 J. Simmons
175 27 J. Simmons
*Event Specific Inputs*
176 27 J. Simmons
177 27 J. Simmons
* configuration: configuruation data (see above)
178 27 J. Simmons
179 27 J. Simmons
h4. Public Layer Details
180 27 J. Simmons
181 27 J. Simmons
*Event Name:* configuration
182 27 J. Simmons
*Event Data:* @{"configuration":<configuration object>}@
183 27 J. Simmons
184 27 J. Simmons
h4. Private Layer Details
185 27 J. Simmons
186 27 J. Simmons
*Serial Message:* @{"event_name":"configuration", "client_id":<socket.id>, "data":{"configuration":<configuration object>}}@
187 27 J. Simmons
188 27 J. Simmons
h3. resistance (event) FUTURE DEVLOPMENT
189 27 J. Simmons
190 27 J. Simmons
*Purpose:* Updates clients on exercise equipment resistance
191 27 J. Simmons
192 27 J. Simmons
h4. Public Layer Details
193 27 J. Simmons
194 27 J. Simmons
TBD
195 27 J. Simmons
196 27 J. Simmons
h4. Private Layer Details
197 27 J. Simmons
198 27 J. Simmons
TBD
199 27 J. Simmons
200 27 J. Simmons
h3. controller_version (message)
201 27 J. Simmons
202 27 J. Simmons
*Purpose:* Inform clients of attached Holoseat device and its hardware and firmare versions (see Version Scheme for details).
203 27 J. Simmons
204 27 J. Simmons
*Message Specific Inputs*
205 27 J. Simmons
206 27 J. Simmons
* type: "controller_version"
207 27 J. Simmons
* message (dictionary): 
208 27 J. Simmons
** device (string): name of connected device (e.g. "Holoseat", "Holoseat Alpha")
209 27 J. Simmons
** hwVer (string): major version number of hardware (e.g. 1)
210 27 J. Simmons
** fwVer (string): major.minor.patch version number of firmware (e.g. 1.0.0)
211 27 J. Simmons
212 27 J. Simmons
h4. Public Layer Details
213 27 J. Simmons
214 27 J. Simmons
*Message Data:* @{"type":"controller_version", "message":{"device":"<device name>", "hwVer":"<major version number>", "fwVer":"<major.minor.patch version number>"}}@
215 27 J. Simmons
216 27 J. Simmons
h4. Private Layer Details
217 27 J. Simmons
218 27 J. Simmons
*Serial Message:* @{"event_name":"message", "client_id":<socket.id>, "data":{"type":"controller_version", "message":{"device":"<device name>", "hwVer":"<major version number>", "fwVer":"<major.minor.patch version number>"}}}@
219 27 J. Simmons
220 27 J. Simmons
h3. controller_error (message)
221 27 J. Simmons
222 27 J. Simmons
*Purpose:* Inform clients of error message
223 27 J. Simmons
224 27 J. Simmons
*Message Specific Data*
225 27 J. Simmons
226 27 J. Simmons
* type: contoller_error
227 27 J. Simmons
* message (string): the error message from the controller
228 27 J. Simmons
229 27 J. Simmons
h4. Public Layer Details
230 27 J. Simmons
231 27 J. Simmons
*Message Data:* @{"type":"controller_error", "message":"<error message>"}@
232 27 J. Simmons
233 27 J. Simmons
h4. Private Layer Details
234 27 J. Simmons
235 27 J. Simmons
*Serial Message:* @{"event_name":"message", "client_id":<socket.id>, "data":{"type":"controller_error", "message":"<error message>"}}@