diff --git a/src/lib/cloud-provider.js b/src/lib/cloud-provider.js new file mode 100644 index 0000000000000000000000000000000000000000..b2c5002870bfebad5ea7630a9d7c817a605b74bf --- /dev/null +++ b/src/lib/cloud-provider.js @@ -0,0 +1,104 @@ +import log from './log.js'; + + +class CloudProvider { + constructor (cloudHost, vm, user, projectId) { + this.vm = vm; + this.username = user; + this.projectId = projectId; + + // Open a websocket connection to the clouddata server + this.openConnection(cloudHost); + } + + /** + * Open a new websocket connection to the clouddata server. + * @param {string} cloudHost The cloud data server to connect to. + */ + openConnection (cloudHost) { + if (window.WebSocket === null) { + log.warn('Websocket support is not available in this browser'); + this.connection = null; + return; + } + + this.connection = new WebSocket((location.protocol === 'http:' ? 'ws://' : 'wss://') + cloudHost); + + this.connection.onerror = e => { + log.error(`Websocket connection error: ${JSON.stringify(e)}`); + + // TODO Add re-connection attempt logic here + }; + + this.connection.onmessage = event => { + const messageString = event.data; + log.info(`Received websocket message: ${messageString}`); + const message = JSON.parse(messageString); + if (message.method === 'set') { + const varData = { + projectId: this.projectId, + varUpdate: { + projectId: message.project_id, + name: message.name, + value: message.value + } + }; + this.vm.postIOData('cloud', varData); + } + }; + + this.connection.onopen = () => { + this.writeToServer('handshake'); + log.info(`Successfully connected to clouddata server.`); + }; + + this.connection.onclose = () => { + log.info(`Closed connection to websocket`); + }; + } + + /** + * Format and send a message to the cloud data server. + * @param {string} methodName The message method, indicating the action to perform. + * @param {string} dataName The name of the cloud variable this message pertains to + * @param {string | number} dataValue The value to set the cloud variable to + * @param {number} dataIndex The index of the item to update (for cloud lists) + * @param {string} dataNewName The new name for the cloud variable (if renaming) + */ + writeToServer (methodName, dataName, dataValue, dataIndex, dataNewName) { + const msg = {}; + msg.method = methodName; + msg.user = this.username; + msg.project_id = this.projectId; + + if (dataName) msg.name = dataName; + if (dataValue) msg.value = dataValue; + if (dataIndex) msg.index = dataIndex; + if (dataNewName) msg.new_name = dataNewName; + + const dataToWrite = JSON.stringify(msg); + this.sendCloudData(dataToWrite); + } + + /** + * Send a formatted message to the cloud data server. + * @param {string} data The formatted message to send. + */ + sendCloudData (data) { + this.connection.send(`${data}\n`); + log.info(`Sent message to clouddata server: ${data}`); + } + + /** + * Provides an API for the VM's cloud IO device to update + * a cloud variable on the server. + * @param {string} name The name of the variable to update + * @param {string | number} value The new value for the variable + */ + updateVariable (name, value) { + this.writeToServer('set', name, value); + } + +} + +export default CloudProvider;