The below is intended for developers working on this repository.
We are locking to running MATRIX OS on Node 6.7 until further notice. This is due to a breaking bug in an external dependency.
Clone repo and update submodules (protobufs, apps)
git clone https://github.com/matrix-io/matrix-os.git
git submodule update --init
Use DEBUG=* node index.js
to see all debug messages.
NODE_ENV=dev
will automatically show important debugs.
app, sensor, stream, matrix
example:
To see output from socket streams and apps, do
DEBUG=app,stream
To exclude engine-io from the output, do
DEBUG=*,-engine*
MATRIX_API_SERVER https://dev-api.admobilize.com
MATRIX_STREAMING_SERVER http://dev-mxss.admobilize.com:80
systemd service is found in debian/
. This is the device configuration where MOS starts on boot.
Run with MATRIX_MODE=service
to have the system look for apps
and db
in var/matrix-store
. protos
will be found in usr/share/admobilize
# Make sure to build image on device with `npm run apphost-build`
DOCKER_APPS=true START_APP=clock node index.js
Please note that the application must be registered with the infrastructure to launch. Internet connectivity is only required on boot.
START_APP=monitor node index.js
# find local rpi ip via arp -a, look at first 3 pairs of MAC
>arp -a
raspberrypi.domain (192.168.0.22) at b8:27:eb:84:7c:49
# you'll probably need to sudo this.
> echo "192.168.0.22 m" >> /etc/hosts
# upload public key
> scp ~/.ssh/id_rsa.pub pi@m:~/
# now we don't have to remember the ip
> ssh pi@m
# so pi stops asking for passwords
> cat id_rsa.pub >> .ssh/known_hosts
# symlink to code as `~/mos`
> ln -s matrix-os/ mos/
now `npm run sync` and `npm run watch` will auto upload code changes to your pi@m in the `/mos` folder
to bypass the password prompts
copy your public key
`scp ~/.ssh/id_rsa.pub pi@m:~/.ssh/otherkey`
on pi, add it to the authorized keys file
`cd ~/.ssh; cat otherkey >> authorized_keys`
NO_UPGRADE=true node index.js
Matrix - is the primary global namespace.
.api - access to node-sdk
.db - provides access to local storage
.events - EventEmitter
.activeProcesses - all active apps
.service - all files in /lib/service
.event - all files in /lib/event
.device - all files in /lib/device
See below for more details
Events are at the core of MATRIX OS. This is how information is sent between the applications and the sockets.
Events
app-config - sends an configuration to the infrastructure
app-emit - sends a datapoint to the infrastructure
app-log - sends a log to the infrastructure (only used with CLI now)
app-message - Global Interapp Messaging
app-{appName}-message - Targeted Interapp messaging
sensor-init - initialize a sensor
cli-message - incoming message from CLI
trigger - incoming event from dashboard / cross messaging
token-refresh - get a new token
device-reboot - restart the device
Every file in Matrix.event
that has an init() will run that automatically. This is to populate the event listeners.
On matrix deploy
, configuration is overwritten with config.yaml
. Otherwise, Firebase is the source of configuration truth with a fall back to config.yaml
for defaults.
When an application runs, however, a config.json
is written with the active config, and used for the application.
Applications are managed by /lib/service/manager.js
. Applications can be started by the CLI matrix start
command or by providing a START_APP
env variable with the name of the application. Each application is a discrete node process.
Starting an application does the following:
- Checks config.json
- Stops duplicates
- Handles log and error messages for redirecting to CLI or Terminal
- Routes messages sent from application to infrastructure
- Sets up listeners for inter-app routing
Applications are prompted to install on MATRIX OS via infrastructure commands ( cli-message
with {type:'app-install'}
). These commands include a URL which the Matrix downloads, conducts an npm install
upon, and checks to make sure appropriate sensors are available (todo).
Each app subscribes to the global app messaging channel app-message
.
Each app sets up a targeted messaging channel app-{appname}-message
.
Each app is available for inter device messages, which move on the trigger
channel.
External:
Applications send data with matrix.send()
or matrix.type('foo').send()
Internal:
Data from an app process is captured and routed into the event system as app-emit
events. These events are directed into service.stream.sendDataPoint
, which sends the data point if there is a connection to the Streaming Server, or adds to a local storage queue if no connection is made.
The Streaming Server is contacted with a deviceToken
parameter. Success = auth-ok
message
The first step in establishing a socket connection is to send a device-register
socket message.
If no Streaming Server is visible, Matrix keeps trying with an ever-increasing delay.
SocketEmit
is a custom wrapper around the socket to provide channel and message capabilities. Please use this when you want to send something to the server.
The repo includes a docker-compose.yml
file. This file contains information to run a containerized version of the MATRIX OS. Please make sure you are running either Linux or the native Docker app, and issue:
docker-compose run --service-ports mos [optional command]
The above command will:
- Build the image that contains all required dependencies to run the MATRIX OS.
- Mount the current directory inside
/matrix
dir inside the container, meaning that changes performed on your local file system will show up inside the container as well. - Run
nodemon index.js
inside the container, exposing port 80 on your local machine. It will also reinstall all your node_modules ifREINSTALL_NODE_MODULES: 1
. This is useful in development as helps dealing withnode_modules
in different branches, and avoids ugly bugs with hard-codednode_modules
built in OSX that won't work on Linux.
This flow can play nice with say, MXSS also running in the same machine. More about that soon.
Put this in your .zshrc
alias mm='NODE_ENV=dev node index.js'
alias mdm='NODE_ENV=dev node --debug-brk index.js'
alias ms=__ms
function __ms(){
START_APP=$1 mm
}
alias mds=__mds
function __mds(){
START_APP=$1 mdm
}
Highly recommend node-vim-debugger. Three ssh sessions required.
mds monitor
node-vim-inspector
vim -nb or :nbs from inside vim
:e filepath
^-p to set a breakpoint
^-c to continue
^-n next
^-i step in
^-o step out
^-u up stack
^-d down stack
lib
- holds most of the codelib/device
- is for isolated device interaction utilitieslib/device/drivers
- is for device componentsevent
- events are setup and handled hereservice
- constructors, utilities, protocols, etc
- Duplicate a file from
lib/device/drivers
>sensorname.js
- Update proto in
proto/malos/driver.proto
- Change read method in
sensorname.js
to point to proto message and field name - Change logs and component in
sensorname.js
to point at new sensorname - Update port number in
lib/device/port.js
- Update sensorTypeList in
lib/device/sensor.js
- Route correctly in
apps/lib/init.js
Be sure to deploy test/fixtures/test.matrix
to the device you are going to use. You can run matrix deploy
from inside the folder. We have to install the application vs manually copy it so there are firebase records created.
Sean Canton sean.canton@admobilize.com