Skip to content

Instantly share code, notes, and snippets.

@TotallyInformation
Created November 28, 2020 16:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save TotallyInformation/8fe6e7a3c74d74d9cc87231a4a1fe336 to your computer and use it in GitHub Desktop.
Save TotallyInformation/8fe6e7a3c74d74d9cc87231a4a1fe336 to your computer and use it in GitHub Desktop.
/** Standardised data schema's for IoT Home Automation
*/
const schemas = {
/** network table
* A table of network devices (logical and physical)
* This schema uses a structure suitable for use with VueJS/bootstrap-vue `b-table` options.
* The table is an object of objects with the ID as the primary key
* It is periodically updated by an NMAP scan.
* The hostname, dhcp and description fields can be update from a uibuilder front-end.
* https://home.knightnet.co.uk:1880/admin/network.html
*/
network: {
id: {
key: 'id',
primary: true,
label: 'ID',
dataType: 'string',
thClass: 'd-none',
tdClass: 'd-none', // Don't display this field in tables
eg: 'D8:6C:63:5E:41:5F'
},
mac: {
key: 'mac',
label: 'MAC',
dataType: 'string',
eg: 'D8:6C:63:5E:41:5F'
},
ipaddr: {
key: 'ipaddr',
label: 'IP',
dataType: 'text',
eg: '192.168.1.1'
},
vendor: {
key: 'vendor',
label: 'Vendor',
dataType: 'text',
eg: 'Expressif'
},
updated: {
key: 'updated',
label: 'Updated',
dataType: 'date',
eg: 1581869007000
},
updatedBy: {
key: 'updatedBy',
label: 'By',
dataType: 'text',
eg: 'nmap'
},
srtt: {
key: 'srtt',
label: 'Latency',
dataType: 'number',
eg: 97.269
},
host: {
key: 'host',
label: 'Host Name',
dataType: 'text',
eg: 'pi2.knightnet.co.uk'
},
hostname: {
key: 'hostname',
label: 'Host Descr',
dataType: 'text',
editable: true,
description: 'Device Description',
eg: 'D1M04 - Access Point'
},
dhcp: {
key: 'dhcp',
label: 'DHCP',
dataType: 'text',
editable: true,
description: 'Is IP address set from DHCP?',
eg: 'Yes-Fixed'
},
description: {
key: 'description',
label: 'Description',
dataType: 'text',
editable: true,
eg: 'Some Text'
},
},
/** Table of physical & logical IoT devices
* Used to track operational data for known devices.
* Used to map logical device names to physical ID's
* e.g. when setting `switch01`, mapping to physical ID and output channel to turn the relay on/off.
*/
known_devices: {
/* Object Key */
name: '{String} Unique',
/* Required Properties */
location: '{ENUM} Short description - see `locations` global',
description: '{String} Description of device',
type: '{String} Description of device type',
id: '{String} <source>/<unique id>[-<Optional channel #>] Technical ID including leading protocol to ensure uniqueness',
source: '{ENUM} ["LAN", "433"] How the device communicates with Node-RED',
input: '{Boolean} Does this device take input? e.g. a switch/relay/bell sounder',
output: '{Boolean} Does this device produce output? e.g. a sensor or a controller',
in_use: '{Boolean} Is this device actively being used?',
/* Optional Properties */
controls: '{Integer} Number of controls (buttons or sensors) that produce control output (e.g. to turn things on/off)',
sensors: '{String Array} Codes for all the sensors on board. See the `sensors` schema',
info: {
// For RFX devices (To send to RFX, `protocol/physical_id/id_channel`)
src_channel: '{ENUM} Input/Output channel from/to source. e.g. `RFX/lights`',
protocol: '{ENUM} [EasyESP, LIGHTWAVERF, ...]',
physical_id: '{String} Optional. e.g. hex id for 433mhz devices',
id_channel: '{Integer} Channel number for those devices that use settable channels (e.g. switches)',
// For networked devices
//protocol: '{String} description of protocol, e.g. `Tasmota`, `EasyESP`, `Custom`',
mac: '{String} Network MAC address of devices network interface. Only for LAN sources.',
ip: '{IP Address} IP Address of devices network interface. Only for Net or LAN sources.',
url: '{url} URL of web interface for the device. Only if it has one.',
// optional
aka: '{String} If I/O from device also appears on a different ID',
geo: '{Array[lat,lon]} Geolocation of device'
},
/* Operational Data - added at runtime */
status: {
online: '{Boolean} Is the device considered to be online?',
updated: '{Timestamp}',
updated_by: '{String} What process/service updated the operational data?',
last_on: '{Timestamp} Last time device turned on (for a switch) or came online (for a network device)',
last_off: '{Timestamp} Last time device turned off (for a switch) or went offline (for a network device)',
on_duration: '{Integer ms} Duration device has been turned on for, was last turned on for (or similarly online for if a network device)',
off_duration: '{Integer ms} Duration device has been turned off for, was last turned off for (or similarly offline for if a network device)',
rssi: '{Integer} Measure of radio strength',
rssiMax: '{Integer} Largest RSSI measured',
rssiMin: '{Integer} Smallest RSSI measured',
battery: '{Integer %} Measure of battery',
memory: '{Integer %} Memory in use',
uptime: '{HH:mm:ss} Elapsed tim the device has been up for',
last_restart: '{Timestamp} Last time device restarted',
last_restart_reason: '{String} What caused the last restart?',
// Other device specific entries may be here
},
outputs: {
/* Sensor outputs - matches the sensor_types list */
'<sensor_name>': '{Number|Boolean|String} The value output from the sensor.'
},
inputs: {
/** Allows data/commands to be sent to IoT devices
* TODO: Need a way to define allowed input commands
*/
'<input_id>': {
state: '{On|Off} State of switch',
updated: '{Date} Last update of any kind',
last_on: '{Date} Last time of On status',
last_off: '{Date} Last time of Off status',
on_duration: '{Integer} ms elapsed between last on and last off',
off_duration: '{Integer} ms elapsed between last off and last on',
},
},
switches: {
/* Input Switch status & last on/off timestamps - 1 entry for each # controls */
'<switch_number>': {
state: '{On|Off} State of switch',
updated: '{Date} Last update of any kind',
last_on: '{Date} Last time of On status',
last_off: '{Date} Last time of Off status',
on_duration: '{Integer} ms elapsed between last on and last off',
off_duration: '{Integer} ms elapsed between last off and last on',
},
},
},
deviceids: {
/** Same as known_devices but key'd by device ID instead of name.
* Automatically generated when known_devices changes.
* Enables easy matching of incoming data with the device name.
*/
},
/** Controller map
* Maps controller inputs to controlled devices (e.g. Switches)
*/
controller_map: {
input_name: '{String} Name (from known_devices)',
input_switch: '{Number}',
output: [ // can be any number of entries
'Known_Id Name',
],
},
locations: {
/** See locations json */
},
protocols: {
/** Actual protocol used */
'EasyESP': 'ESP',
'Tasmota': 'ESP',
'LIGHTWAVERF': '433MHz Siemens Lightwave-RF',
'AC': '433MHz HomeEasy EU',
'ti_home2': 'Totally Information`s home2 MQTT schema',
'Custom': 'Other or unknown protocol/schema',
},
sources: {
/** Where does this signal come from? */
'NET': 'General TCP/IP networking, OS service name as ID as this is a logical rather than physical source',
'LAN': 'Wired or Wi-Fi network, MAC address as ID (upper case, colon separated)',
'433': '433MHz wireless. e.g. RFXtrx433e, Unique Hex code as ID',
},
/** The different sensor types allowed in the `sensors` list property
* of the known_devices table.
*/
sensor_types: {
'temperature': 'Temperature (degrees celsius)',
'humidity': 'Relative humidity (%)',
'light': 'Light intensity (Lumens)',
'pressure': 'Sea-level equivalent pressure (mbar)',
'movement': 'Movement (1,0) e.g. PIR or mag door sensor',
'switch': 'Switch (On/Off) e.g. push button, latch, etc',
'sound': 'Sound (1/0)',
'energy': 'Energy (Watts)',
'voltage': 'Voltage (Volts)',
'current': 'Current (amps)',
},
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment