File size: 5,635 Bytes
30c32c8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
const Variable = require('../engine/variable');
const log = require('../util/log');

class Cloud {
    /**
     * @typedef updateVariable
     * @param {string} name The name of the cloud variable to update on the server
     * @param {(string | number)} value The value to update the cloud variable with.
     */

    /**
     * A cloud data provider, responsible for managing the connection to the
     * cloud data server and for posting data about cloud data activity to
     * this IO device.
     * @typedef {object} CloudProvider
     * @property {updateVariable} updateVariable A function which sends a cloud variable
     * update to the cloud data server.
     * @property {Function} requestCloseConnection A function which closes
     * the connection to the cloud data server.
     */

    /**
     * Part of a cloud io data post indicating a cloud variable update.
     * @typedef {object} VarUpdateData
     * @property {string} name The name of the variable to update
     * @property {(number | string)} value The scalar value to update the variable with
     */

    /**
     * A cloud io data post message.
     * @typedef {object} CloudIOData
     * @property {VarUpdateData} varUpdate A {@link VarUpdateData} message indicating
     * a cloud variable update
     */

    /**
     * Cloud IO Device responsible for sending and receiving messages from
     * cloud provider (mananging the cloud server connection) and interacting
     * with cloud variables in the current project.
     * @param {Runtime} runtime The runtime context for this cloud io device.
     */
    constructor (runtime) {
        /**
         * Reference to the cloud data provider, responsible for mananging
         * the web socket connection to the cloud data server.
         * @type {?CloudProvider}
         */
        this.provider = null;

        /**
         * Reference to the runtime that owns this cloud io device.
         * @type {!Runtime}
         */
        this.runtime = runtime;

        /**
         * Reference to the stage target which owns the cloud variables
         * in the project.
         * @type {?Target}
         */
        this.stage = null;
    }

    /**
     * Set a reference to the cloud data provider.
     * @param {CloudProvider} provider The cloud data provider
     */
    setProvider (provider) {
        this.provider = provider;
    }

    /**
     * Set a reference to the stage target which owns the
     * cloud variables in the project.
     * @param {Target} stage The stage target
     */
    setStage (stage) {
        this.stage = stage;
    }

    /**
     * Handle incoming data to this io device.
     * @param {CloudIOData} data The {@link CloudIOData} object to process
     */
    postData (data) {
        if (data.varUpdate) {
            this.updateCloudVariable(data.varUpdate);
        }
    }

    requestCreateVariable (variable) {
        if (this.runtime.canAddCloudVariable()) {
            if (this.provider) {
                this.provider.createVariable(variable.name, variable.value);
                // We'll set the cloud flag and update the
                // cloud variable limit when we actually
                // get a confirmation from the cloud data server
            }
        } // TODO else track creation for later
    }

    /**
     * Request the cloud data provider to update the given variable with
     * the given value. Does nothing if this io device does not have a provider set.
     * @param {string} name The name of the variable to update
     * @param {string | number} value The value to update the variable with
     */
    requestUpdateVariable (name, value) {
        if (this.provider) {
            this.provider.updateVariable(name, value);
        }
    }

    /**
     * Request the cloud data provider to rename the variable with the given name
     * to the given new name. Does nothing if this io device does not have a provider set.
     * @param {string} oldName The name of the variable to rename
     * @param {string | number} newName The new name for the variable
     */
    requestRenameVariable (oldName, newName) {
        if (this.provider) {
            this.provider.renameVariable(oldName, newName);
        }
    }

    /**
     * Request the cloud data provider to delete the variable with the given name
     * Does nothing if this io device does not have a provider set.
     * @param {string} name The name of the variable to delete
     */
    requestDeleteVariable (name) {
        if (this.provider) {
            this.provider.deleteVariable(name);
        }
    }

    /**
     * Update a cloud variable in the runtime based on the message received
     * from the cloud provider.
     * @param {VarData} varUpdate A {@link VarData} object describing
     * a cloud variable update received from the cloud data provider.
     */
    updateCloudVariable (varUpdate) {
        const varName = varUpdate.name;

        const variable = this.stage.lookupVariableByNameAndType(varName, Variable.SCALAR_TYPE);
        if (!variable || !variable.isCloud) {
            log.warn(`Received an update for a cloud variable that does not exist: ${varName}`);
            return;
        }

        variable.value = varUpdate.value;
    }

    /**
     * Request the cloud data provider to close the web socket connection and
     * clear this io device of references to the cloud data provider and the
     * stage.
     */
    clear () {
        if (!this.provider) return;

        this.provider.requestCloseConnection();
        this.provider = null;
        this.stage = null;
    }
}

module.exports = Cloud;