pimatic
Version:
A home automation server and framework for the Raspberry PI running on node.js
1,496 lines (1,471 loc) • 35.1 kB
text/coffeescript
###
API-Defs
=========
###
assert = require 'assert'
t = require('decl-api').types
###
#Rules
###
api = {}
###
#Framework
###
device = {
type: t.object
toJson: yes
properties:
id:
description: "A user chosen string, used to identify that device."
type: t.string
name:
description: "A user chosen string that should be used to display the device."
type: t.string
template:
description: "Name of the template, that should be used to display the device."
type: t.string
attributes:
description: "List of all attributes of the device."
type: t.array
actions:
description: "List of all actions of the device."
type: t.array
config:
description: "Config of the device, without default values."
type: t.object
configDefaults:
description: "Default values for the config options."
type: t.object
}
page = {
type: t.object
properties:
id:
description: "A user chosen string, used to identify the page."
type: t.string
name:
description: "A user chosen string that should be used to display the page."
type: t.string
devices:
description: "List of all device ids that should be displayed on that page"
type: t.array
items:
deviceItem:
type: t.object
properties:
deviceId:
description: "The id of the device to display at that position"
type: t.string
}
api.framework = {
events:
deviceAdded:
description: "A new device was added to the devices list"
params:
device:
type: t.object
toJson: yes
deviceAttributeChanged:
description: "The value of a device attribute changed"
params:
event:
type: t.object
properties:
device:
type: t.object
toJson: yes
attributeName:
type: t.string
attribute:
type: t.object
time:
type: t.date
value:
type: t.any
messageLogged:
description: "A new log message was emitted"
params:
event:
type: t.object
properties:
level:
type: t.string
msg:
type: t.string
meta:
type: t.object
actions:
getGuiSettings:
description: "Get the GUI config options"
rest:
type: "GET"
url: "/api/config/settings/gui"
result:
guiSettings:
type: "object"
properties:
config:
type: "object"
defaults:
type: "object"
restart:
description: "Restart pimatic"
rest:
type: "POST"
url: "/api/restart"
result:
void: {}
permission:
action: "restart"
getConfig:
description: "Get the config, fields will be blank if no password was provided"
rest:
type: "GET"
url: '/api/config'
params:
password:
type: t.string
optional: yes
result:
config:
description: "The config"
type: t.object
permission:
scope: "config"
access: "read"
updateConfig:
description: "Update the config"
rest:
type: "POST"
url: '/api/config'
params:
config:
type: t.object
permission:
scope: "config"
access: "write"
}
api.devices = {
actions:
getDevices:
description: "List all devices."
rest:
type: "GET"
url: "/api/devices"
params: {}
result:
devices:
description: "Array of all devices."
type: t.array
toJson: yes
items:
device: device
permission:
scope: "devices"
access: "read"
getDeviceById:
description: "Retrieve a device by a given ID."
rest:
type: "GET"
url: "/api/devices/:deviceId"
params:
deviceId:
description: "The ID of the device that should be returned."
type: t.string
result:
device:
description: "The requested device or null if the device was not found."
type: t.object
toJson: yes
properties: device.properties
permission:
scope: "devices"
access: "read"
updateDeviceOrder:
rest:
type: "POST"
url: "/api/devices"
description: "Update the order of all devices"
params:
deviceOrder:
type: t.array
result:
deviceOrder:
type: t.array
permission:
scope: "devices"
access: "write"
getDeviceClasses:
description: "List all registered device classes."
rest:
type: "GET"
url: "/api/device-class"
result:
deviceClasses:
type: t.array
permission:
scope: "devices"
access: "read"
getDeviceConfigSchema:
description: "Get the config schema of a device class."
rest:
type: "GET"
url: "/api/device-class/:className"
params:
className:
type: t.string
result:
configSchema:
type: t.object
permission:
scope: "devices"
access: "read"
addDeviceByConfig:
description: "Add a device by config values"
rest:
type: "POST"
url: "/api/device-config"
params:
deviceConfig:
type: t.object
result:
device: device
permission:
scope: "devices"
access: "write"
updateDeviceByConfig:
description: "Update a device by config values"
rest:
type: "PATCH"
url: "/api/device-config"
params:
deviceConfig:
type: t.object
result:
device: device
permission:
scope: "devices"
access: "write"
removeDevice:
description: "Remove a device from the framework an config"
rest:
type: "DELETE"
url: "/api/device-config/:deviceId"
params:
deviceId:
type: t.string
result:
device: device
permission:
scope: "devices"
access: "write"
discoverDevices:
description: "Start to scan for new devices"
rest:
type: "POST"
url: "/api/discover-devices"
params:
time:
type: t.number
optional: yes
permission:
scope: "devices"
access: "write"
callDeviceAction:
description: "Calls the action of the given device"
rest:
type: "GET"
url: "/api/device/:deviceId/:actionName"
handler: "callDeviceActionReq"
socket:
handler: "callDeviceActionSocket"
params:
deviceId:
type: t.string
actionName:
type: t.string
permission:
action: 'controlDevices'
}
api.rules = {
actions:
addRuleByString:
description: "Add a rule by a string"
rest:
type: "POST"
url: "/api/rules/:ruleId"
params:
ruleId:
type: t.string
rule:
type: t.object
properties:
name:
type: t.string
ruleString:
type: t.string
active:
type: t.boolean
optional: yes
logging:
type: t.boolean
optional: yes
force:
type: t.boolean
optional: yes
permission:
scope: "rules"
access: "write"
updateRuleByString:
rest:
type: "PATCH"
url: "/api/rules/:ruleId"
description: "Update a rule by a string"
params:
ruleId:
type: t.string
rule:
type: t.object
properties:
name:
type: t.string
optional: yes
ruleString:
type: t.string
optional: yes
active:
type: t.boolean
optional: yes
logging:
type: t.boolean
optional: yes
permission:
scope: "rules"
access: "write"
removeRule:
rest:
type: "DELETE"
url: "/api/rules/:ruleId"
description: "Remove the rule with the given ID"
params:
ruleId:
type: t.string
permission:
scope: "rules"
access: "write"
getRules:
rest:
type: "GET"
url: "/api/rules"
description: "List all rules"
params: {}
result:
rules:
type: t.array
toJson: yes
permission:
scope: "rules"
access: "write"
getRuleById:
rest:
type: "GET"
url: "/api/rules/:ruleId"
description: "List all rules"
params:
ruleId:
type: t.string
result:
rule:
type: "object"
toJson: yes
permission:
scope: "rules"
access: "read"
getRuleActionsHints:
rest:
type: "POST"
url: "/api/rules-parser/get-actions-hints"
description: "Get hints for the rule actions input field"
params:
actionsInput:
type: t.string
result:
hints:
type: t.object
properties:
actions:
type: t.array
tokens:
type: t.array
autocomplete:
type: t.array
errors:
type: t.array
warnings:
type: t.array
format:
type: t.array
permission:
scope: "rules"
access: "read"
getRuleConditionHints:
rest:
type: "POST"
url: "/api/rules-parser/get-condition-hints"
description: "Get hints for the rule condition input field"
params:
conditionInput:
type: t.string
result:
hints:
type: t.object
properties:
predicates:
type: t.array
tokens:
type: t.array
autocomplete:
type: t.array
errors:
type: t.array
warnings:
type: t.array
format:
type: t.array
permission:
scope: "rules"
access: "read"
getPredicatePresets:
rest:
type: "GET"
url: "/api/rules-parser/get-predicate-presets"
description: "Get predicates the user can choose from"
params: {}
result:
presets:
type: "array"
permission:
scope: "rules"
access: "read"
getPredicateInfo:
rest:
type: "GET"
url: "/api/rules-parser/get-predicate-info"
description: "Get predicates info"
params: {
input:
type: "string"
predicateProviderClass:
type: "string"
optional: yes
}
result:
result:
type: "array"
permission:
scope: "rules"
access: "read"
executeAction:
rest:
type: "POST"
url: "/api/execute-action"
description: "Execute a rule action by a given string"
params:
actionString:
description: "The action to execute"
type: t.string
simulate:
description: "If it is true then only simulate the action."
type: t.boolean
optional: yes
logging:
description: "Log result message"
type: t.string
optional: yes
result:
message:
type: t.string
permission:
scope: "rules"
access: "write"
updateRuleOrder:
rest:
type: "POST"
url: "/api/rules"
description: "Update the order of all rules"
params:
ruleOrder:
type: t.array
result:
ruleOrder:
type: t.array
permission:
scope: "rules"
access: "write"
}
api.pages = {
actions:
getPages:
description: "List all pages."
rest:
type: "GET"
url: "/api/pages"
params: {}
result:
pages:
type: t.array
items:
page: page
permission:
scope: "pages"
access: "read"
getPageById:
description: "Get a page by ID"
rest:
type: "GET"
url: "/api/pages/:pageId"
params:
pageId:
description: "The ID of the page that should be returned."
type: t.string
result:
page:
description: "The requested page or null if the page was not found."
type: t.object
properties: page.properties
permission:
scope: "pages"
access: "read"
removePage:
description: "Remove a page."
rest:
type: "DELETE"
url: "/api/pages/:pageId"
params:
pageId:
description: "The ID of the page that should be removed."
type: t.string
result:
removed:
description: "The removed page."
type: t.object
properties: page.properties
permission:
scope: "pages"
access: "write"
addPage:
rest:
type: "POST"
url: "/api/pages/:pageId"
description: "Add a page."
params:
pageId:
description: "The ID of the page that should be added."
type: t.string
page:
description: "Object with ID and name of the page to create."
type: t.object
properties:
name:
description: "A user chosen string that should be used to display the page."
type: t.string
result:
page:
description: "The created page."
type: t.object
properties: page.properties
permission:
scope: "pages"
access: "write"
updatePage:
description: "Update a page name or device order."
rest:
type: "PATCH"
url: "/api/pages/:pageId"
params:
pageId:
description: "The ID of the page to change."
type: t.string
page:
description: "An object with properties that should be updated."
type: t.object
properties:
name:
description: "The new name to set."
type: t.string
optional: yes
devicesOrder:
description: "Array of ordered deviceIDs."
type: t.array
optional: yes
items:
deviceId:
type: t.string
result:
page:
description: "The updated page."
type: t.object
properties: page.properties
permission:
scope: "pages"
access: "write"
addDeviceToPage:
rest:
type: "POST"
url: "/api/pages/:pageId/devices/:deviceId"
description: "Add a page"
params:
pageId:
type: t.string
deviceId:
type: t.string
result:
page:
type: t.object
permission:
scope: "pages"
access: "write"
removeDeviceFromPage:
rest:
type: "DELETE"
url: "/api/pages/:pageId/devices/:deviceId"
description: "Remove a device from a group."
params:
pageId:
type: t.string
deviceId:
type: t.string
result:
page:
type: t.object
permission:
scope: "pages"
access: "write"
updatePageOrder:
rest:
type: "POST"
url: "/api/pages"
description: "Update the order of all pages"
params:
pageOrder:
type: t.array
result:
pageOrder:
type: t.array
permission:
scope: "pages"
access: "write"
}
api.groups = {
actions:
getGroups:
description: "List all groups."
rest:
type: "GET"
url: "/api/groups"
params: {}
result:
groups:
type: t.array
items:
group:
type: t.object
permission:
scope: "groups"
access: "read"
removeGroup:
description: "Remove group"
rest:
type: "DELETE"
url: "/api/groups/:groupId"
params:
groupId:
type: t.string
result:
removed:
type: t.object
permission:
scope: "groups"
access: "write"
addGroup:
rest:
type: "POST"
url: "/api/groups/:groupId"
description: "Add a group"
params:
groupId:
type: t.string
group:
type: t.object
result:
group:
type: t.object
permission:
scope: "groups"
access: "write"
updateGroup:
rest:
type: "PATCH"
url: "/api/groups/:groupId"
description: "Update a group"
params:
groupId:
type: t.string
group:
type: t.object
properties:
name:
type: t.name
optional: yes
devicesOrder:
type: t.array
optional: yes
variablesOrder:
type: t.array
optional: yes
rulesOrder:
type: t.array
optional: yes
result:
group:
type: t.object
permission:
scope: "groups"
access: "write"
addDeviceToGroup:
rest:
type: "POST"
url: "/api/groups/:groupId/devices/:deviceId"
description: "Add a device to a group"
params:
groupId:
type: t.string
deviceId:
type: t.string
result:
deviceItem:
type: t.object
permission:
scope: "groups"
access: "write"
removeDeviceFromGroup:
rest:
type: "DELETE"
url: "/api/groups/:groupId/devices/:deviceId"
description: "Remove a device from a group"
params:
groupId:
type: t.string
deviceId:
type: t.string
result:
group:
type: t.object
permission:
scope: "groups"
access: "write"
addRuleToGroup:
rest:
type: "POST"
url: "/api/groups/:groupId/rules/:ruleId"
description: "Add a rule to a group"
params:
groupId:
type: t.string
ruleId:
type: t.string
position:
type: t.number
optional: yes
result:
group:
type: t.object
permission:
scope: "rules"
access: "write"
removeRuleFromGroup:
rest:
type: "DELETE"
url: "/api/groups/:groupId/rules/:ruleId"
description: "Remove a rule from a group"
params:
groupId:
type: t.string
ruleId:
type: t.string
result:
group:
type: t.object
permission:
scope: "rules"
access: "write"
updateRuleGroupOrder:
rest:
type: "POST"
url: "/api/groups/:groupId/rules"
description: "Add a rule to a group"
params:
groupId:
type: t.string
ruleOrder:
type: t.array
result:
group:
type: t.object
permission:
scope: "rules"
access: "write"
addVariableToGroup:
rest:
type: "POST"
url: "/api/groups/:groupId/variables/:variableName"
description: "Add a variable to a group"
params:
groupId:
type: t.string
variableName:
type: t.string
position:
type: t.number
optional: yes
result:
group:
type: t.object
permission:
scope: "variables"
access: "write"
updateDeviceGroupOrder:
rest:
type: "POST"
url: "/api/groups/:groupId/devices"
description: "Update device order in group"
params:
groupId:
type: t.string
deviceOrder:
type: t.array
result:
group:
type: t.object
permission:
scope: "devices"
access: "write"
removeVariableFromGroup:
rest:
type: "DELETE"
url: "/api/groups/:groupId/variables/:variableName"
description: "Remove a variable from a group"
params:
groupId:
type: t.string
variableName:
type: t.string
result:
group:
type: t.object
permission:
scope: "variables"
access: "write"
updateVariableGroupOrder:
rest:
type: "POST"
url: "/api/groups/:groupId/variables"
description: "Update variable order in group"
params:
groupId:
type: t.string
variableOrder:
type: t.array
result:
group:
type: t.object
permission:
scope: "variables"
access: "write"
updateGroupOrder:
rest:
type: "POST"
url: "/api/groups"
description: "Update the order of all groups"
params:
groupOrder:
type: t.array
result:
groupOrder:
type: t.array
permission:
scope: "groups"
access: "write"
}
###
#Variables
###
variableParams = {
name:
type: t.string
type:
type: t.string
enum: ["expression", "value"]
valueOrExpression:
type: t.string
unit:
type: t.string
optional: yes
}
variableResult = {
variable:
type: t.object
toJson: yes
}
api.variables = {
actions:
getVariables:
description: "List all variables"
rest:
type: "GET"
url: "/api/variables"
params: {}
result:
variables:
type: t.array
toJson: yes
permission:
scope: "variables"
access: "read"
updateVariable:
description: "Update a variable value or expression"
rest:
type: "PATCH"
url: "/api/variables/:name"
params: variableParams
result: variableResult
permission:
scope: "variables"
access: "write"
addVariable:
description: "Add a value or expression variable"
rest:
type: "POST"
url: "/api/variables/:name"
params: variableParams
result: variableResult
permission:
scope: "variables"
access: "write"
getVariableByName:
description: "Get infos about a variable"
rest:
type: "GET"
url: "/api/variables/:name"
params:
name:
type: t.string
result: variableResult
permission:
scope: "variables"
access: "read"
removeVariable:
description: "Remove a variable"
rest:
type: "DELETE"
url: "/api/variables/:name"
params:
name:
type: t.string
permission:
scope: "variables"
access: "write"
result: variableResult
updateVariableOrder:
rest:
type: "POST"
url: "/api/variables"
description: "Update the order of all variables"
params:
variableOrder:
type: t.array
result:
variableOrder:
type: t.array
permission:
scope: "variables"
access: "write"
}
###
#Plugins
###
api.plugins = {
actions:
getInstalledPluginsWithInfo:
description: "List all installed plugins"
rest:
type: "GET"
url: "/api/plugins"
params: {}
result:
plugins:
type: t.array
permission:
scope: "plugins"
access: "read"
searchForPluginsWithInfo:
description: "Search for available plugins"
rest:
type: "GET"
url: "/api/available-plugins"
params: {}
result:
plugins:
type: t.array
permission:
scope: "plugins"
access: "read"
getOutdatedPlugins:
description: "Get outdated plugins"
rest:
type: "GET"
url: "/api/outdated-plugins"
params: {}
result:
outdatedPlugins:
type: t.array
permission:
scope: "updates"
access: "read"
isPimaticOutdated:
description: "Is pimatic outdated"
rest:
type: "GET"
url: "/api/outdated-pimatic"
params: {}
result:
outdated:
tye: 'any'
permission:
scope: "updates"
access: "read"
installUpdatesAsync:
description: "Install updates without awaiting result"
rest:
type: "POST"
url: "/api/update-async"
params:
modules:
type: t.array
result:
status:
type: 'any'
permission:
scope: "updates"
access: "write"
uninstallPlugin:
description: "Uninstalls a plugin completely"
rest:
type: "DELETE"
url: "/api/plugins/:name"
params:
name:
type: t.string
permission:
scope: "updates"
access: "write"
removePluginFromConfig:
description: "Remove a plugin from config"
rest:
type: "DELETE"
url: "/api/config/plugins"
params:
pluginName:
type: t.string
result:
removed:
type: t.boolean
permission:
scope: "plugins"
access: "write"
setPluginActivated:
description: "Set active state of the plugin"
rest:
type: "POST"
url: "/api/config/plugins-active"
params:
pluginName:
type: t.string
active:
type: t.boolean
result:
pluginUpdated:
type: t.boolean
permission:
scope: "plugins"
access: "write"
getUpdateProcessStatus:
description: "Get update status"
rest:
type: "GET"
url: "/api/update-process"
result:
info:
type: "object"
permission:
scope: "updates"
access: "none"
getPluginConfigSchema:
description: "Get the config schema of a plugin name (must be installed)."
rest:
type: "GET"
url: "/api/plugin-config-schema/:pluginName"
params:
pluginName:
type: t.string
result:
configSchema:
type: t.object
permission:
scope: "plugins"
access: "read"
getPluginConfig:
description: "Get the config of a plugin."
rest:
type: "GET"
url: "/api/plugin-config/:pluginName"
params:
pluginName:
type: t.string
result:
config:
type: t.object
permission:
scope: "plugins"
access: "read"
updatePluginConfig:
description: "Update the config of a plugin."
rest:
type: "POST"
url: "/api/plugin-config/:pluginName"
params:
pluginName:
type: t.string
config:
type: t.object
permission:
scope: "plugins"
access: "write"
doesRequireRestart:
description: "Check if a restart is required."
rest:
type: "GET"
url: "/api/restart-required"
result:
restartRequired:
type: t.boolean
permission:
scope: "plugins"
access: "read"
}
###
#Database
###
messageCriteria = {
criteria:
type: t.object
optional: yes
properties:
level:
type: 'any'
optional: yes
levelOp:
type: t.string
optional: yes
after:
type: t.date
optional: yes
before:
type: t.date
optional: yes
limit:
type: t.number
optional: yes
}
dataCriteria = {
criteria:
type: t.object
optional: yes
properties:
deviceId:
type: [t.string, t.array]
optional: yes
attributeName:
type: [t.string, t.array]
optional: yes
after:
type: t.date
optional: yes
before:
type: t.date
optional: yes
order:
type: t.string
optional: yes
orderDirection:
type: t.string
optional: yes
offset:
type: t.number
optional: yes
limit:
type: t.number
optional: yes
}
api.database = {
actions:
queryMessages:
description: "List log messages"
rest:
type: 'GET'
url: '/api/database/messages'
params: messageCriteria
result:
messages:
type: t.array
permission:
scope: "messages"
access: "read"
deleteMessages:
description: "Delete messages older than the given date"
rest:
type: 'DELETE'
url: '/api/database/messages'
params: messageCriteria
permission:
scope: "messages"
access: "write"
addDeviceAttributeLogging:
description: "Enable or disable logging for an device attribute"
params:
deviceId:
type: t.string
attributeName:
type: t.string
time:
type: t.any
permission:
scope: "events"
access: "read"
queryMessagesTags:
description: "List all tags from the matching messages"
rest:
type: 'GET'
url: '/api/database/messages/tags'
params: messageCriteria
result:
tags:
type: t.array
permission:
scope: "messages"
access: "read"
queryMessagesCount:
description: "Count of all matches matching the criteria"
rest:
type: 'GET'
url: '/api/database/messages/count'
params: messageCriteria
result:
count:
type: t.number
permission:
scope: "messages"
access: "read"
queryDeviceAttributeEvents:
rest:
type: 'GET'
url: '/api/database/device-attributes/'
description: "Get logged values of device attributes"
params: dataCriteria
result:
events:
type: t.array
permission:
scope: "events"
access: "read"
queryDeviceAttributeEventsCount:
rest:
type: 'GET'
url: '/api/database/device-attributes/count'
description: "Get count of saved device attributes events"
params: {}
result:
count:
type: t.number
permission:
scope: "events"
access: "read"
queryDeviceAttributeEventsCounts:
rest:
type: 'GET'
url: '/api/database/device-attributes/counts'
description: "Get count of saved device attributes per attribute"
params: {}
result:
counts:
type: t.array
permission:
scope: "events"
access: "read"
queryDeviceAttributeEventsDevices:
rest:
type: 'GET'
url: '/api/database/device-attributes/devices'
description: "Get all device attribute infos in database"
params: {}
result:
devices:
type: t.array
permission:
scope: "events"
access: "read"
queryDeviceAttributeEventsInfo:
rest:
type: 'GET'
url: '/api/database/device-attributes-info'
description: "Get all device attribute infos in database"
params: {}
result:
deviceAttributes:
type: t.array
permission:
scope: "events"
access: "read"
querySingleDeviceAttributeEvents:
rest:
type: 'GET'
url: '/api/database/device-attributes/:deviceId/:attributeName'
description: "Get logged values of device attributes"
params:
deviceId:
type: t.string
attributeName:
type: t.string
criteria:
type: t.object
optional: yes
properties:
after:
type: t.date
optional: yes
before:
type: t.date
optional: yes
groupByTime:
type: t.number
optional: yes
order:
type: t.string
optional: yes
orderDirection:
type: t.string
optional: yes
offset:
type: t.number
optional: yes
limit:
type: t.number
optional: yes
result:
events:
type: t.array
permission:
scope: "events"
access: "read"
getDeviceAttributeLogging:
description: "Get device attribute logging times table"
params: {}
result:
attributeLogging:
type: t.array
permission:
scope: "events"
access: "read"
setDeviceAttributeLogging:
description: "Set device attribute logging times table"
params:
attributeLogging:
type: t.array
permission:
scope: "events"
access: "write"
getDeviceAttributeLoggingTime:
description: "Get device attribute logging times table"
params:
deviceId:
type: t.string
attributeName:
type: t.string
result:
timeInfo:
type: t.object
permission:
scope: "events"
access: "read"
runVacuum:
description: "Run the sqlite3 vacuum pragma"
params: {}
rest:
type: 'GET'
url: '/api/database/vacuum'
permission:
scope: "database"
access: "write"
checkDatabase:
description: "Check database and config integrity"
params: {}
rest:
type: 'GET'
url: '/api/database/check'
result:
problems:
type: t.array
permission:
scope: "database"
access: "write"
deleteDeviceAttribute:
description: "Delete a device attribute from the database"
rest:
type: 'DELETE'
url: '/api/database/device-attribute/by-id'
params:
id:
type: "number"
permission:
scope: "database"
access: "write"
updateDeviceAttribute:
description: "Updates a device attribute info in database"
rest:
type: 'PATCH'
url: '/api/database/device-attribute/by-id'
params:
id:
type: "number"
permission:
scope: "database"
access: "write"
}
# all
actions = {}
apis = [
api.framework,
api.rules,
api.variables,
api.plugins,
api.database,
api.groups,
api.pages
api.devices
]
for a in apis
for actionName, action of a.actions
assert(not actions[actionName]?)
actions[actionName] = action
api.all = {actions}
module.exports = api