Open mauricebasement opened 8 years ago
Various access methods can be used to get/set values. These should be wrapped into the “driver”. Some examples might be:
initial proposal - some proposals may conflict.
the system is made up of a horizontal-hierarchy. That is, there is main controller, the Brain, and / or 1 or more modules. Each module is able to function on it's own, such that the main controller is essentially a module as well. Each module contains devices (can, may not, doesn't have to), and has varying degrees of autonomy; that is, it may or may not have a clock source, it may or may not provide some functions available from the Brain. Each module should be network-able (ideally with wi-fi), or Bluetooth LE enabled. Serial Port connections should also be possible. All data between modules should be transported in JSON. It is up to the module implementer to handle JSON data structures.
The module should be able to register itself with the Brain, and pending user controlled approval, the Brain will assume configuration and management tasks for the module, so that the user has one entry point into the larger system. Individual modules not registered with the Brain must implement their own configuration interface, while maintaining configuration and management compatibility with the brain.
The Brain provides 3 primary functions (2 of which are optional). They consist of:
The Brain proposes to manage a set of devices locally, or remotely. It will have a time source (NTP, Radio Clock, Settable RTC), and network access.
Devices, or Modules (collections of devices), will be defined, monitored and updated, so that it will store a full definition of the entire system - including remote modules, storage locations (historical and analytical may be elsewhere), users, logical locations for module groupings, schedules, and recent state histories.
This should be fully represented via JSON.
The brain, and/or modules, should be able to monitor resource (device) states/values and set a variety of conditions to be tested. Where possible, automated responses should be available.
Resource Monitoring should define:
Automated Response should define:
InfluxDB provides time series, mongoDB, couchDB, others provide NoSQL JSON stores. It should also be possible to use RRDtool, however it's power lies in charting, and I've not explored it's query capabilities.
Visualization may be done with D3.js, chartist.js, or others.
To be clarified: objects should be "append-able", that is, the container should be able to chain meta-data onto them. e.g. a device attached to a smart module might have "local" meta-data, which is only accessible to the smart module. this means that device should have a base representation (exportable), and a detailed representation (internal to implementor). Anything that imports the object should be able to add data - for ex. in the case of the smart module itself, the brain might add, "online: true|false", "lastContact: Date object", etc. Such information may not be relevant to the smart module, but can be relevant to the brain.
Such meta-data can be defined as public and private to the various objects. That is, each object may have it's own private metadata, but represent a "public" sub-set to entities in messages. This may look like, from the device level, a detailed set of data to interact with itself, but it may represent itself to the controller entity as an addressable generic entity, or clients. What the Module/Brain sees
{ "class": "sensor", "type": "temp", "units": "degrees C", "value": 25.0, "_id": "long-unique-id" }
What the device looks like
{ "class": "sensor", "type": "temp", "units": "degrees C", "_id": "long-unique-id",
"getTemp": "function(this.pin){ let this.value = value; return value };",
"pin": "D7",
"toF": "function(this.value) { return ((9/5*this.value) + 32 ) };",
"lastVal": 25.0
"lastValTime": 1477596705000
}
where the "getTemp" & "toF" are methods, and "lastVal" & "lastValTime" are private to the device object.
this applies much more identifiably to http, but i'm sure its describable via MQTT messages as well, so that the topic is the "resource", but the read, write, update, delete becomes difficult, or at least a little bit more complicated, so that the brain subscribes to a device-topic and publishes to a device-topic, as does the device.
additionally, external data can be accessed via REST, directly from a front end client.
Should Haves:
nomenclature
curl -X POST|GET|DELETE -H "Content-Type: application/json" -d '{ varString: "string", varArray: [ 1, 2, 3], varObject: { subVar: "string" }}'
Example: to get the status of a relay (on or off) from a module, you could use the following, curl -X GET -H "Content-Type: application/json" http://module/devices/:dev_UUID:
where dev_UUID is a 64bit string identifying the particular device. It should return something like:
{
_id: "2bb91460881b7d5a98418060b0006d66",
name: "Electrical Outlet 1",
state: "on",
watts: 124,
volts: 230
}
these object definitions are non-functional, provide no relationships or UUID for entities, etc. This would need to be taken into account
With this kind of information, the server (brain), and the client, and the modules, will be able to 'do' things, e.g. present a drag and drop gui, provide inputs for historical data queries, be inputs to other objects (conditions, etc.), be outputs for response objects, etc.
pref1: { proto: 'http', read: 'GET', update 'POST', create: 'POST', delete: 'DELETE'},
pref2: { proto: 'mqtt', ...}}
By everything communicating over the brain, you can have a central control point, however, the definition of that control could be limited to initial configuration, with the configuration being transmitted to a resource for autonomous implementation - e.g. schedules, default monitoring, etc, can be stored on a module in case the connection to the brain goes down for whatever reason. Further, an already configured module can be added to a "brain" easily, or recovered in the case of previous brain failures.
{
"zone": 2,
"type": "tent",
"vendor": "Secret Jardin",
"vendorURL": "http://www.secretjardin.com/",
"model": "DR100",
"modelURL": "http://www.secretjardin.com/en/grow-tent-secret-jardin/vintage-growtent-secret-jardin.html",
"imageURL": "http://www.secretjardin.com/images/artsexylightbox_tmp/ca67ddef1e8f55b9f61662bb444b56f7_420_412.png",
"length": [
100,
"cm"
],
"width": [
100,
"cm"
],
"height": [
200,
"cm"
],
"installDate": "2016-05-01",
"contains": {
"lamp": {
"type": "LED",
"watts": 330,
"vendor": "BML",
"vendorURL": "http://www.bmlhorticutlure.com",
"model": "SPYDR 600",
"modelURL": "http://www.bmlhorticulture.com/spydr-600-grow-max-spectrum/",
"imageURL": "http://cdn2.bigcommerce.com/n-pktq5q/qzuvsqy/products/136/images/482/spydr_1200_1_small__82589.1417557271.1280.1280.jpg?c=2",
"install_date": "2015-08-01",
"lifetime": "5 yrs",
"PowerPortGPIO": 67,
"dimmable": "0-10v",
"pwmPortPin": "P9_14",
"pwmCtrl": 3
},
"filter": {
"type": "Carbon",
"rating": 500,
"ratingUnit": "m3/h",
"vendor": "Phresh Filters",
"vendorURL": "http://www.phreshfilters.com",
"productURL": "http://www.phreshfilter.com/products/phresh-filters.aspx",
"installDate": "2015-8-1",
"lifetime": "2 yrs",
"maint": "4 months"
},
"fan": {
"type": [
"inline",
"exhaust"
],
"id": 1,
"name": "fanB",
"rating": 650,
"ratingUnit": "m3/h",
"PowerPortGPIO": 67,
"dimmable": "manual",
"vendor": "Prima Klima",
"model": "PK125",
"vendorURL": "http://www.primaklima.biz/",
"productURL": "http://www.primaklima.biz/tempctrl.html",
"inServiceDate": "2015-8-1"
},
"sensor": {
"dht22": {
"driver": "dht",
"driverPath": "/root/workspace/intellistrip/bin",
"provides": [
"temp",
"humidity"
],
"units": [
"C",
"%"
]
}
}
},
"_id": 2
}
It's time to get started defining objects, events and messages. Each of these will be used to configure / manage / monitor & respond / provide state and results, etc. Regardless of the language used, objects can/should have methods implemented, such that they can be accessed via the REST API (e.g. http://module.local/conditions/temp-fan-assoc/start - would begin monitoring the temperature and adjusting a fan accordingly, or http://module.local/schedules/every-20-mins/pump-1a/start - would associate the device, pump-1a, with the schedule, 'every-20-mins', and start executing the schedule [turning the pump on every 20 mins, for some period of time], or, http://module.local/schedules/every-day-at-21/light-group-1/on would turn a group of lights on at 21:00, and http://module.local/schedules/every-day-at-9/light-group-1/off would turn the same group off).
The architecture of the software needs to be evident on the GitHub project page, so it is possible for other people to get an overview of the project and "how stuff works".