Using Your own javascript and html files You are able to generate full application to communicate with your devices.
Documentation is available here
Soon We will provide real documentation
To write your own component or integrate with remoteMe.org
pelase check main sources:
https://github.com/remoteme/RemoteMeWebPageLibrary
the files You should start with integration are remoteMe.js it includes core functionality
and variables.js it has variable supports.
The good way of start is to read sourcecode generate by wizard, and by remoteMeComponents.js
Below under transactions:
Introduction to advanced programming of websites
In simple cases, all you need is html files, javascript generates by wizards, more about which is here and here. In more advanced scenarios, I suggest using libraries that will describe the quick start in this article. Source codes can be found here
In these examples, I show communication on the example of websites (opened in two different browser tabs, in the same way you can send data to ESP and RPi devices).
By reading this article, be sure to read the article about webPages in RemoteMe
How it’s working
RemoteMe hosts the pages in the cloud, the maximum file size is 200KB, which should be enough for the purposes in which RemoteMe was created, but when you need more space – please contact me.
In the websites for communication with the RemoteMe system, libraries should be used. Libraries easily allow communication with the system itself. In general, all communication with the system takes place through:
- websocket connection – most of the communication is based on sending binary websocket messages in a special message format. The format of the message to be viewed in the sources
- REST Api rest functions are available here
In most cases, even for advanced scenarios, the javascript libraries whose full source code can be found here are enough. They significantly simplify the implementation of solutions and I will use these libraries in this article.
(For the most advanced scenarios of the own desktop management interface (whether a desktop or mobile application) it is necessary to implement sending messages and using REST api)
Website from scratch
security
In order for the user to view websites must be logged in (one of three methods – username and password, token (used eg in QR codes), download a special token based on username and password of the user). Otherwise, error code 401 will be returned when attempting to download files
import
Import libraries, styles – the easiest way is to copy them from the newly created website created from the default settings and the default template.
1 2 3 |
<script src="/libs/remoteMe.js"></script> <script src="/libs/remoteMeMessages.js"></script> <script src="/libs/variables.js"></script> |
- remoteMe.js – RemoteMe class – connection to RemoteMe and ensures sending and receiving messages (also ping messages)
- remoteMeMessages.js – functions, classes that allow you to easily build messages to send and parse received messages
- variables.js -functions that facilitate communication on the basis of variables
1 2 |
<link rel="stylesheet" type="text/css" href="styles.css"> <script src="script.js"></script> |
Imports the css and javascript files of the user, which are located after expanding the website’s belt – you can add new javascript files, css and import them in a similar way.
Constants in files
Files can use constants that will be converted when the page serves it to the user (upper/lowe case are irrelevant):
- ####deviceId# – – converted into a number – website deviceId
- ####username# – userName of logged user
- ####raspberrypideviceid# -deviceId of the first RasbperryPi found – when there is no RasbperryPi – returns 0
- ####arduinodeviceid# – deviceId of the first Arduino found – when there is no Arduino – returns 0
The simplest website
The site below only connects to the RemoteMe system and maintains the connection. In addition, it will write to the consoles about change of the connection status. (for maximum simplicity, the javascript code is also in the html code)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
<html> <head> <meta charset="utf-8"> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> <script src="/libs/remoteMe.js"></script> <script src="/libs/remoteMeMessages.js"></script> <script src="/libs/remoteMeApiRest.js"></script> <script src="/libs/variables.js"></script> </head> <script> var thisDeviceId=####deviceId#; </script> <body> <button onClick="connect()">connect</button> <button onClick="disconnect()">disconnect</button> <script> function connect(){ RemoteMe.getInstance().connectWebSocket(); } function disconnect(){ RemoteMe.getInstance().disconnectWebSocket(); } function onWebSocketChange(status){ switch(status){ case ConnectingStatusEnum.CONNECTED: console.info("Connected");break; case ConnectingStatusEnum.DISCONNECTED: console.info("Disconnected");break; case ConnectingStatusEnum.FAILED: console.info("Failed");break; case ConnectingStatusEnum.CONNECTING: console.info("Connecting");break; case ConnectingStatusEnum.DISCONNECTING: console.info("Disconnecting");break; case ConnectingStatusEnum.CHECKING: console.info("Checking");break; } } new RemoteMe({automaticlyConnectWS:false,webSocketConnectionChange:[onWebSocketChange]}); </script> </body> </html> |
The script is designed to connect to RemoteMe and disconnect after pressing the buttons.
var thisDeviceId=####deviceId#;
id of our device – it is used by libraries and must be assigned to a global variable thisDeviceId
.
new RemoteMe({automaticlyConnectWS:false,webSocketConnectionChange:[onWebSocketChange]});
screation of the RemoteMe class object, in configuration (available in the sources), we inform that we do not want to connect to the RemoteMe system immediately, and that each time we change the status of the connection function onWebSocketChange:
is called
1 2 3 4 5 6 7 8 9 10 |
function onWebSocketChange(status){ switch(status){ case ConnectingStatusEnum.CONNECTED: console.info("Connected");break; case ConnectingStatusEnum.DISCONNECTED: console.info("Disconnected");break; case ConnectingStatusEnum.FAILED: console.info("Failed");break; case ConnectingStatusEnum.CONNECTING: console.info("Connecting");break; case ConnectingStatusEnum.DISCONNECTING: console.info("Disconnecting");break; case ConnectingStatusEnum.CHECKING: console.info("Checking");break; } } |
The onWebSocketChange function receives as a parameter the current status of the webSocket connection. the status is number type and ConectinStatusEnum
is an enumeration type for easier recognition of the connection status.
RemoteMe.getInstance()
because you can not create a second RemoteMe object, the easiest way to refer to remoteMe is to use the getInstance
function when the object was not created before it will be created with the default settings.
A page in the device manager
- a single html file
- the status of the connection to the site
After opening the website (index.html-> open in new Tab) we will get:
After clicking connect, the web page will connect to the system, Connection status (2) will change to connected, and in the console logs we will receive relevant information.
Modification and reading of the state of variables
reminder: variables – they have type and value, are observed by devices – change on one device is propagated to other listening devices. More about variables here
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
<html> <head> <meta charset="utf-8"> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> <script src="/libs/remoteMe.js"></script> <script src="/libs/remoteMeMessages.js"></script> <script src="/libs/remoteMeApiRest.js"></script> <script src="/libs/variables.js"></script> </head> <script> var thisDeviceId=####deviceId#; </script> <body> <button onClick="change(1)">change to 1</button> <button onClick="change(Math.floor(Math.random() * 1000) + 1 )">change to random</button> <br/>result: <div id='resultDivId'></div> <script> function change(value){ console.info(`we will set value into ${value}`); RemoteMe.getInstance().getVariables().setInteger("someName",value); } RemoteMe.getInstance().afterWebSocketConneced(()=>{ RemoteMe.getInstance().getVariables().observeInteger("someName",value=>{ console.info(`Value was changed into ${value}`); $("#resultDivId").html(value); }); }); </script> </body> </html> |
To test the operation, I suggest opening the page in few different tabs:
Changing the value of a variable on one tab changes the value of the variable in the other tabs. The current state of the variable is also shown in the “Variables” tab in the system, where it is also possible to modify the variable value.
Code overview:
1 2 3 4 |
function change(value){ console.info(`we will set value into ${value}`); RemoteMe.getInstance().getVariables().setInteger("someName",value); } |
1 2 3 4 |
RemoteMe.getInstance().getVariables().observeInteger("someName",value=>{ console.info(`Value was changed into ${value}`); $("#resultDivId").html(value); }); |
In the file: variables.js There are equivalents of the observeInteger and setIntger functions for other types. Of course, as our variable is changed by a device other than a website, and another device listens to change the variable value, we do the same.
sending a message
As far as the variables have a specific type and are sent to all listening devices, in some cases it is useful to send a message of any type to a specific device. In RemoteMe this is done by sending messages. Messages are in the form of a byte array, there are functions in the RemoteMe libraries to easily manipulate such a table. The system supports two types of messages:
- asynchroniczne -asynchronous – we send a message to a specific device and do not expect a response – eg message turn on the light
- synchronous – messages with which we are waiting for an answer, eg – what is the temperature in the room
(examples of how to light up or read the temperature in most cases should be implemented using variables, but I wanted the message to be clear)
Sending an asynchronous message
We will start by sending an asynchronous message. We will need two WWW devices, one with the name sender of any Id- and the second with Id= 1 – named receiver, DeviceId is important in this case , because to this deviceId we will send a message to the page “sender”. Of course, the page “receiver” can also send messages as well but i didn’t implement it because i didn’t want to blur the source code
sender index.html:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
<html> <head> <meta charset="utf-8"> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> <script src="/libs/remoteMe.js"></script> <script src="/libs/remoteMeMessages.js"></script> <script src="/libs/remoteMeApiRest.js"></script> <script src="/libs/variables.js"></script> </head> <script> var thisDeviceId=####deviceId#; </script> <body> <button onClick="send([1,2,3,5,8,13,21])">send fibonacci</button> <button onClick="send([2, 3, 5, 7, 11, 13, 17])">send primar</button> <button onClick="send([-123456,123456,1234567890123])">send somebig numbers</button> <script> function send(toSend){ let data= new RemoteMeData(2+toSend.length*4); data.putUint16(toSend.length); toSend.forEach(v=>{ data.putInt32(v); }); console.info(`array to sent is ${data.getArray()}`); RemoteMe.getInstance().sendUserMessage(1,data.getArray()); } RemoteMe.getInstance();//this will automaticly connect </script> </body> </html> |
The page sends numbers to the receiver (Fibonacci numbers, primar numbers, and large numbers where the last one is too big to send). When we send messages, it is delivered as an array of bytes, so we need to know how to decode / encode it.
First, create a message buffor: let data= new RemoteMeData(2+toSend.length*4);
classRemoteMeData
has methods for easily saving variables like putShort, putString (more in sources remoteMeMessages.js ). When creating a buffer, you must specify its size. size depends on the message format itself:
In my case, in the byte array, the first two bytes (as a non-signed 16-bit int) is count of numbers in the message: data.putUint16(toSend.length);
(2 bytes) then writes to each number into buffer , each number has a size of 4 bytes, hence the size of the buffer.Next RemoteMe.getInstance().sendUserMessage(1,data.getArray());
we send data into deviceId=1 device
receiver (deviceId ) index.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
<html> <head> <meta charset="utf-8"> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> <script src="/libs/remoteMe.js"></script> <script src="/libs/remoteMeMessages.js"></script> <script src="/libs/remoteMeApiRest.js"></script> <script src="/libs/variables.js"></script> </head> <script> var thisDeviceId=####deviceId#; </script> <body> <script> function onMessage(senderDeviceId,dataRaw){ let data = new RemoteMeData(dataRaw); let size=data.popUint16(); let numbers=[]; while(size--!=0){ numbers.push(data.popInt32()); } console.info(`got message from device : ${senderDeviceId} with ${numbers} numbers `); } new RemoteMe({onUserMessage:onMessage}); </script> </body> </html> |
In the constructor new RemoteMe({onUserMessage:onMessage});
I specify what function the library should call when the message arrives. The function as the first argument will have the sending device id, and as the second parameter the byte array (as the DataView type object) in the function onMessage
is wrapping DataView
by RemoteMeData
so that it would be easier to read the numbers, then I get the first number (2 byte int unsigned ) and then I get all numbers because i know how many numbers I can pop . Finally, it prints numbers.
Both devices in the device manager should look like this:
After open both devices in separate tabs in the receiver’s console, we will have written the numbers sent by the “sender” device, each time the sender button is pressed. In the same way we receive and send messages to other devices (ESP, RPi, application on android etc)
Send a synchronous message
So we send a message and look forward to the response – useful when you want to “ask a question to our ESP”. In the example, we will create two websites, one will ask for the sum of adding two numbers, the other will do the calculations and respond.
sender index.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
<html> <head> <meta charset="utf-8"> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> <script src="/libs/remoteMe.js"></script> <script src="/libs/remoteMeMessages.js"></script> <script src="/libs/remoteMeApiRest.js"></script> <script src="/libs/variables.js"></script> </head> <script> var thisDeviceId=####deviceId#; </script> <body> <button onClick="ask(2,2)">2+2 </button> <button onClick="ask(-12345,3456)">-12345 + 3456</button> <button onClick="ask(1.2345,3.456)">1.2345 + 3.456</button> <script> function ask(v1,v2){ let data= new RemoteMeData(16);//float used is 8bytes length data.putFloat64(v1); data.putFloat64(v2); console.info(`ask what is ${v1} + ${v2}`); RemoteMe.getInstance().sendUserSyncMessage(1,data.getArray(),(dataRaw)=>{ let data = new RemoteMeData(dataRaw); let result=data.popFloat64(); console.info(` ${v1} + ${v2} is ${result}`); alert(`${v1} + ${v2} = ${result}`) }); } RemoteMe.getInstance();//this will automaticly connect </script> </body> </html> |
by function
1 2 3 4 5 6 |
RemoteMe.getInstance().sendUserSyncMessage(1,data.getArray(),(dataRaw)=>{ let data = new RemoteMeData(dataRaw); let result=data.popFloat64(); console.info(` ${v1} + ${v2} is ${result}`); alert(`${v1} + ${v2} = ${result}`) }); |
to the device with id = 1 we send an inquiry. In the message body there are two variables of the Float64 type, after receiving the answer, the function given as the third argument is call, the function parameter is the response as a byte table that we decode and display.
Receiver index.html (deviceId:1)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
<html> <head> <meta charset="utf-8"> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> <script src="/libs/remoteMe.js"></script> <script src="/libs/remoteMeMessages.js"></script> <script src="/libs/remoteMeApiRest.js"></script> <script src="/libs/variables.js"></script> </head> <script> var thisDeviceId=####deviceId#; </script> <body> <script> function onSyncMessage(senderDeviceId,dataRaw){ let data = new RemoteMeData(dataRaw); let v1=data.popFloat64(); let v2=data.popFloat64(); console.info(`got to sum : ${v1} and ${v2} `); let toReturn= new RemoteMeData(8); toReturn.putFloat64( v1+v2); return toReturn.getArray(); } new RemoteMe({onUserSyncMessage:onSyncMessage}); </script> </body> </html> |
In the remoteMe constructor we specify what function to be call when an asynchronous message arrives. Then in the indicated function we decode the message and return the byte arrays containing one Float64 type number. After launching the pages in two different browser tabs, after clicking the buttons we will get the result from the addition returned by the page opened in the second tab.