thingmodel
Version:
Synchronize data and models across multiple devices
1,146 lines (946 loc) • 85.3 kB
JavaScript
var WebSocket = require('ws'),_ = require('lodash');
console.debug = console.log;
var dcodeIO = {ProtoBuf: require('protobufjs')};
var ThingModel;
(function (ThingModel) {
var BuildANewThing = (function () {
function BuildANewThing(type) {
this.type = type;
}
Object.defineProperty(BuildANewThing, "WithoutType", {
get: function () {
return new BuildANewThing(null);
},
enumerable: true,
configurable: true
});
BuildANewThing.As = function (type) {
return new BuildANewThing(type);
};
BuildANewThing.prototype.IdentifiedBy = function (id) {
return new ThingPropertyBuilder(new ThingModel.Thing(id, this.type));
};
return BuildANewThing;
})();
ThingModel.BuildANewThing = BuildANewThing;
var ThingPropertyBuilder = (function () {
function ThingPropertyBuilder(thing) {
this.thing = thing;
this.ContainingA = this;
this.ContainingAn = this;
this.AndA = this;
this.AndAn = this;
}
ThingPropertyBuilder.prototype.String = function (key, value) {
this.thing.SetProperty(new ThingModel.Property.String(key, value));
return this;
};
ThingPropertyBuilder.prototype.Double = function (key, value) {
this.thing.SetProperty(new ThingModel.Property.Double(key, value));
return this;
};
ThingPropertyBuilder.prototype.Int = function (key, value) {
this.thing.SetProperty(new ThingModel.Property.Int(key, value));
return this;
};
ThingPropertyBuilder.prototype.Boolean = function (key, value) {
this.thing.SetProperty(new ThingModel.Property.Boolean(key, value));
return this;
};
ThingPropertyBuilder.prototype.DateTime = function (key, value) {
this.thing.SetProperty(new ThingModel.Property.DateTime(key, value));
return this;
};
ThingPropertyBuilder.prototype.Location = function (mixed, value) {
var key;
if (typeof value !== "undefined") {
key = mixed;
} else {
key = "location";
value = mixed;
}
if (!value)
return this;
switch (value.type) {
case "equatorial":
this.thing.SetProperty(new ThingModel.Property.Location.Equatorial(key, value));
break;
case "latlng":
this.thing.SetProperty(new ThingModel.Property.Location.LatLng(key, value));
break;
case "point":
default:
this.thing.SetProperty(new ThingModel.Property.Location.Point(key, value));
break;
}
return this;
};
ThingPropertyBuilder.prototype.Build = function () {
return this.thing;
};
return ThingPropertyBuilder;
})();
ThingModel.ThingPropertyBuilder = ThingPropertyBuilder;
})(ThingModel || (ThingModel = {}));
var ThingModel;
(function (ThingModel) {
var BuildANewThingType = (function () {
function BuildANewThingType() {
}
BuildANewThingType.Named = function (name) {
return new ThingTypePropertyBuilder(new ThingModel.ThingType(name));
};
return BuildANewThingType;
})();
ThingModel.BuildANewThingType = BuildANewThingType;
var ThingTypePropertyBuilder = (function () {
function ThingTypePropertyBuilder(type) {
this.type = type;
this.ContainingA = this;
this.ContainingAn = this;
this.AndA = this;
this.AndAn = this;
}
Object.defineProperty(ThingTypePropertyBuilder.prototype, "NotRequired", {
get: function () {
this.nextPropertyIsNotRequired = true;
return this;
},
enumerable: true,
configurable: true
});
ThingTypePropertyBuilder.prototype.WhichIs = function (description) {
if (!this.lastProperty) {
this.type.Description = description;
} else {
this.lastProperty.Description = description;
}
return this;
};
ThingTypePropertyBuilder.prototype._createProperty = function (key, name, type) {
if (!this.lastPropertyAdded && this.lastProperty != null) {
this.type.DefineProperty(this.lastProperty);
this.lastPropertyAdded = false;
}
var prop = new ThingModel.PropertyType(key, type, true);
prop.Name = name;
if (this.nextPropertyIsNotRequired) {
this.nextPropertyIsNotRequired = false;
prop.Required = false;
}
this.lastProperty = prop;
};
ThingTypePropertyBuilder.prototype.String = function (key, name) {
this._createProperty(key, name, 5 /* String */);
return this;
};
ThingTypePropertyBuilder.prototype.LocationPoint = function (key, name) {
if (typeof key === "undefined") { key = "location"; }
this._createProperty(key, name, 2 /* LocationPoint */);
return this;
};
ThingTypePropertyBuilder.prototype.LocationLatLng = function (key, name) {
if (typeof key === "undefined") { key = "location"; }
this._createProperty(key, name, 3 /* LocationLatLng */);
return this;
};
ThingTypePropertyBuilder.prototype.LocationEquatorial = function (key, name) {
if (typeof key === "undefined") { key = "location"; }
this._createProperty(key, name, 4 /* LocationEquatorial */);
return this;
};
ThingTypePropertyBuilder.prototype.Double = function (key, name) {
this._createProperty(key, name, 6 /* Double */);
return this;
};
ThingTypePropertyBuilder.prototype.Int = function (key, name) {
this._createProperty(key, name, 7 /* Int */);
return this;
};
ThingTypePropertyBuilder.prototype.Boolean = function (key, name) {
this._createProperty(key, name, 8 /* Boolean */);
return this;
};
ThingTypePropertyBuilder.prototype.DateTime = function (key, name) {
this._createProperty(key, name, 9 /* DateTime */);
return this;
};
ThingTypePropertyBuilder.prototype.CopyOf = function (otherType) {
var _this = this;
_.each(otherType.Properties, function (propertyType) {
_this.type.DefineProperty(propertyType.Clone());
});
return this;
};
ThingTypePropertyBuilder.prototype.Build = function () {
if (!this.lastPropertyAdded && this.lastProperty != null) {
this.type.DefineProperty(this.lastProperty);
}
return this.type;
};
return ThingTypePropertyBuilder;
})();
ThingModel.ThingTypePropertyBuilder = ThingTypePropertyBuilder;
})(ThingModel || (ThingModel = {}));
var ThingModel;
(function (ThingModel) {
(function (WebSockets) {
var Client = (function () {
function Client(senderID, path, warehouse) {
this._connexionDelay = 2000;
this.SenderID = senderID;
this._path = path;
this._warehouse = warehouse;
this._thingModelObserver = new ThingModel.Proto.ProtoModelObserver();
warehouse.RegisterObserver(this._thingModelObserver);
this._fromProtobuf = new ThingModel.Proto.FromProtobuf(this._warehouse);
this._toProtobuf = new ThingModel.Proto.ToProtobuf();
this._closed = true;
this._reconnection = false;
this._observers = null;
this._sendMessageWaitingList = [];
this.Connect();
}
Client.prototype.Connect = function () {
var _this = this;
if (!this._closed) {
return;
}
this._ws = new WebSocket(this._path);
this._ws.onopen = function () {
console.info("ThingModel: Open connection");
_this._closed = false;
_this._fromProtobuf = new ThingModel.Proto.FromProtobuf(_this._warehouse);
_this._toProtobuf = new ThingModel.Proto.ToProtobuf();
_this._connexionDelay = 2000;
var firstOpen = !_this._reconnection;
if (_this._sendMessageWaitingList.length > 0) {
_.each(_this._sendMessageWaitingList, function (message) {
_this.SendMessage(message);
});
_this._sendMessageWaitingList = [];
}
_this.Send();
if (firstOpen) {
_this.NotifyObservers(function (obs) {
return obs.OnFirstOpen();
});
}
_this.NotifyObservers(function (obs) {
return obs.OnOpen();
});
};
this._ws.onclose = function () {
if (!_this._closed) {
_this._closed = true;
console.info("ThingModel: Connection lost");
_this.NotifyObservers(function (obs) {
return obs.OnClose();
});
}
_this._reconnection = true;
setTimeout(function () {
return _this.Connect();
}, _this._connexionDelay);
if (_this._connexionDelay < 20000) {
_this._connexionDelay += 3500;
}
};
var useFileReader = typeof FileReader !== "undefined";
this._ws.onmessage = function (message) {
var data = message.data;
if (typeof data === "string") {
console.info("ThingModel has received a string: " + message);
} else if (useFileReader) {
var fileReader = new FileReader();
fileReader.readAsArrayBuffer(data);
fileReader.onload = function () {
return _this.parseBuffer(fileReader.result);
};
} else {
_this.parseBuffer(data);
}
};
};
Client.prototype.parseBuffer = function (buffer) {
var senderName = this._fromProtobuf.Convert(buffer);
console.debug("ThingModel: message from: " + senderName);
this._toProtobuf.ApplyThingsSuppressions(_.values(this._thingModelObserver.Deletions));
this._thingModelObserver.Reset();
this.NotifyObservers(function (obs) {
return obs.OnTransaction(senderName);
});
};
Client.prototype.Send = function () {
if (this._closed) {
console.debug("ThingModel: Does not send, waiting for connexion");
return;
}
if (this._thingModelObserver.SomethingChanged) {
var transaction = this._thingModelObserver.GetTransaction(this._toProtobuf, this.SenderID, this._reconnection);
this._ws.send(this._toProtobuf.ConvertTransaction(transaction));
this._thingModelObserver.Reset();
this._reconnection = false;
console.debug("ThingModel: transaction sent");
this.NotifyObservers(function (obs) {
return obs.OnSend();
});
}
};
Client.prototype.SendMessage = function (message) {
if (this._closed) {
this._sendMessageWaitingList.push(message);
} else {
this._ws.send(message);
}
};
Client.prototype.Close = function () {
if (!this._closed) {
this._ws.close();
this._closed = true;
}
};
Client.prototype.IsConnected = function () {
return this._closed;
};
Client.prototype.RegisterObserver = function (observer) {
if (this._observers === null) {
this._observers = [observer];
} else {
this._observers.push(observer);
}
};
Client.prototype.UnregisterObserver = function (observer) {
if (this._observers !== null) {
this._observers.splice(_.indexOf(this._observers, observer), 1);
}
};
Client.prototype.NotifyObservers = function (callback) {
if (this._observers !== null) {
_.each(this._observers, callback);
}
};
return Client;
})();
WebSockets.Client = Client;
})(ThingModel.WebSockets || (ThingModel.WebSockets = {}));
var WebSockets = ThingModel.WebSockets;
})(ThingModel || (ThingModel = {}));
var __extends = this.__extends || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
__.prototype = b.prototype;
d.prototype = new __();
};
var ThingModel;
(function (ThingModel) {
(function (WebSockets) {
var ClientEnterpriseEdition = (function (_super) {
__extends(ClientEnterpriseEdition, _super);
function ClientEnterpriseEdition(senderID, path, warehouse) {
_super.call(this, senderID, path, warehouse);
this._isLive = true;
this._isPaused = false;
}
Object.defineProperty(ClientEnterpriseEdition.prototype, "IsLive", {
get: function () {
return this._isLive;
},
enumerable: true,
configurable: true
});
Object.defineProperty(ClientEnterpriseEdition.prototype, "IsPaused", {
get: function () {
return this._isPaused;
},
enumerable: true,
configurable: true
});
ClientEnterpriseEdition.prototype.Live = function () {
if (this._isLive && !this._isPaused)
return;
this.SendMessage("live");
this._isLive = true;
this._isPaused = false;
};
ClientEnterpriseEdition.prototype.Play = function () {
if (!this._isPaused)
return;
this.SendMessage("play");
this._isPaused = false;
};
ClientEnterpriseEdition.prototype.Pause = function () {
if (this._isPaused)
return;
this.SendMessage("pause");
this._isPaused = true;
};
ClientEnterpriseEdition.prototype.Load = function (time) {
this.SendMessage("load " + time.getTime());
this._isLive = false;
this._isPaused = true;
};
ClientEnterpriseEdition.prototype.Send = function () {
if (!this._isLive || this._isPaused) {
console.debug("ThingModelClientEnterpriseEdition cannot send data while paused or in a past situation");
return;
}
_super.prototype.Send.call(this);
};
return ClientEnterpriseEdition;
})(WebSockets.Client);
WebSockets.ClientEnterpriseEdition = ClientEnterpriseEdition;
})(ThingModel.WebSockets || (ThingModel.WebSockets = {}));
var WebSockets = ThingModel.WebSockets;
})(ThingModel || (ThingModel = {}));
var ThingModel;
(function (ThingModel) {
(function (Proto) {
var FromProtobuf = (function () {
function FromProtobuf(warehouse) {
this._warehouse = warehouse;
this.StringDeclarations = {};
}
FromProtobuf.prototype.KeyToString = function (key) {
if (key == 0) {
return "";
}
var value = this.StringDeclarations[key];
return typeof value === "undefined" ? "undefined" : value;
};
FromProtobuf.prototype.Convert = function (data, check) {
if (typeof check === "undefined") { check = false; }
var transaction = Proto.ProtoTools.Builder.Transaction.decode(data);
return this.ConvertTransaction(transaction, check);
};
FromProtobuf.prototype.ConvertTransaction = function (transaction, check) {
var _this = this;
_.each(transaction.string_declarations, function (d) {
_this.StringDeclarations[d.key] = d.value;
});
var senderId = this.KeyToString(transaction.string_sender_id);
var thingsToDelete = {};
_.each(transaction.things_remove_list, function (key) {
var id = _this.KeyToString(key);
var thing = _this._warehouse.GetThing(id);
if (thing) {
thingsToDelete[thing.ID] = thing;
}
});
this._warehouse.RemoveCollection(thingsToDelete, true, senderId);
_.each(transaction.thingtypes_declaration_list, function (d) {
_this.ConvertThingTypeDeclaration(d, senderId);
});
var thingsToConnect = [];
_.each(transaction.things_publish_list, function (t) {
var modelThing = _this.ConvertThingPublication(t, check, senderId);
if (t.connections_change) {
thingsToConnect.push({ proto: t, model: modelThing });
}
});
_.each(thingsToConnect, function (tuple) {
tuple.model.DisconnectAll();
_.each(tuple.proto.connections, function (connection) {
var t = _this._warehouse.GetThing(_this.KeyToString(connection));
if (t) {
tuple.model.Connect(t);
}
});
_this._warehouse.RegisterThing(tuple.model, false, false, senderId);
});
return senderId;
};
FromProtobuf.prototype.ConvertThingTypeDeclaration = function (thingType, senderId) {
var _this = this;
var modelType = new ThingModel.ThingType(this.KeyToString(thingType.string_name));
modelType.Description = this.KeyToString(thingType.string_description);
_.each(thingType.properties, function (propertyType) {
var type = null;
switch (propertyType.type) {
case 0 /* LOCATION */:
type = 1 /* Location */;
break;
case 1 /* STRING */:
type = 5 /* String */;
break;
case 2 /* DOUBLE */:
type = 6 /* Double */;
break;
case 3 /* INT */:
type = 7 /* Int */;
break;
case 4 /* BOOLEAN */:
type = 8 /* Boolean */;
break;
case 5 /* DATETIME */:
type = 9 /* DateTime */;
break;
}
var modelProperty = new ThingModel.PropertyType(_this.KeyToString(propertyType.string_key), type, propertyType.required);
modelProperty.Description = _this.KeyToString(propertyType.string_description);
modelProperty.Name = _this.KeyToString(propertyType.string_name);
modelType.DefineProperty(modelProperty);
});
this._warehouse.RegisterType(modelType, true, senderId);
};
FromProtobuf.prototype.ConvertThingPublication = function (thing, check, senderId) {
var _this = this;
var type = null;
if (thing.string_type_name != 0) {
type = this._warehouse.GetThingType(this.KeyToString(thing.string_type_name));
}
var id = this.KeyToString(thing.string_id);
var modelThing = this._warehouse.GetThing(id);
if (modelThing == null || (modelThing.Type == null && type != null || type == null && modelThing.Type != null || (modelThing.Type != null && type != null && modelThing.Type.Name != type.Name))) {
modelThing = new ThingModel.Thing(id, type);
}
_.each(thing.properties, function (property) {
_this.ConvertThingProperty(property, modelThing);
});
if (check && type != null && !type.Check(modelThing)) {
console.log("Object «" + id + "» from «" + senderId + "»not valid, ignored");
} else if (!thing.connections_change) {
this._warehouse.RegisterThing(modelThing, false, false, senderId);
}
return modelThing;
};
FromProtobuf.prototype.ConvertLocationProperty = function (location, property) {
if (property.location_value != null) {
location.X = property.location_value.x;
location.Y = property.location_value.y;
if (!property.location_value.z_null) {
location.Z = property.location_value.z;
}
}
};
FromProtobuf.prototype.ConvertThingProperty = function (property, modelThing) {
var modelProperty = null;
var key = this.KeyToString(property.string_key);
switch (property.type) {
case 2 /* LOCATION_EQUATORIAL */:
var locEquatorial = new ThingModel.Location.Equatorial();
this.ConvertLocationProperty(locEquatorial, property);
modelProperty = new ThingModel.Property.Location.Equatorial(key, locEquatorial);
break;
case 0 /* LOCATION_POINT */:
var locPoint = new ThingModel.Location.Point();
this.ConvertLocationProperty(locPoint, property);
modelProperty = new ThingModel.Property.Location.Point(key, locPoint);
break;
case 1 /* LOCATION_LATLNG */:
var locLatLng = new ThingModel.Location.LatLng();
this.ConvertLocationProperty(locLatLng, property);
modelProperty = new ThingModel.Property.Location.LatLng(key, locLatLng);
break;
case 3 /* STRING */:
var value;
if (property.string_value != null) {
value = property.string_value.value;
if (!value && property.string_value.string_value != 0) {
value = this.KeyToString(property.string_value.string_value);
}
} else {
value = "undefined";
}
modelProperty = new ThingModel.Property.String(key, value);
break;
case 4 /* DOUBLE */:
modelProperty = new ThingModel.Property.Double(key, property.double_value);
break;
case 5 /* INT */:
modelProperty = new ThingModel.Property.Int(key, property.int_value);
break;
case 6 /* BOOLEAN */:
modelProperty = new ThingModel.Property.Boolean(key, property.boolean_value);
break;
case 7 /* DATETIME */:
modelProperty = new ThingModel.Property.DateTime(key, new Date(property.datetime_value.toNumber()));
break;
}
modelThing.SetProperty(modelProperty);
};
return FromProtobuf;
})();
Proto.FromProtobuf = FromProtobuf;
})(ThingModel.Proto || (ThingModel.Proto = {}));
var Proto = ThingModel.Proto;
})(ThingModel || (ThingModel = {}));
var ThingModel;
(function (ThingModel) {
(function (Proto) {
var ProtoModelObserver = (function () {
function ProtoModelObserver() {
this.Updates = {};
this.Deletions = {};
this.Definitions = {};
this.PermanentDefinitions = {};
this.somethingChanged = false;
}
ProtoModelObserver.prototype.Reset = function () {
this.Updates = {};
this.Deletions = {};
this.Definitions = {};
this.somethingChanged = true;
};
ProtoModelObserver.prototype.New = function (thing) {
this.Updates[thing.ID] = thing;
this.somethingChanged = true;
};
ProtoModelObserver.prototype.Deleted = function (thing) {
delete this.Updates[thing.ID];
this.Deletions[thing.ID] = thing;
this.somethingChanged = true;
};
ProtoModelObserver.prototype.Updated = function (thing) {
this.Updates[thing.ID] = thing;
this.somethingChanged = true;
};
ProtoModelObserver.prototype.Define = function (thingType) {
this.Definitions[thingType.Name] = thingType;
this.PermanentDefinitions[thingType.Name] = thingType;
this.somethingChanged = true;
};
Object.defineProperty(ProtoModelObserver.prototype, "SomethingChanged", {
get: function () {
return this.somethingChanged;
},
enumerable: true,
configurable: true
});
ProtoModelObserver.prototype.GetTransaction = function (toProtobuf, senderID, allDefinitions, onlyDefinitions) {
if (typeof allDefinitions === "undefined") { allDefinitions = false; }
if (typeof onlyDefinitions === "undefined") { onlyDefinitions = false; }
return toProtobuf.Convert(onlyDefinitions ? [] : _.values(this.Updates), _.values(this.Deletions), _.values(allDefinitions ? this.PermanentDefinitions : this.Definitions), senderID);
};
return ProtoModelObserver;
})();
Proto.ProtoModelObserver = ProtoModelObserver;
})(ThingModel.Proto || (ThingModel.Proto = {}));
var Proto = ThingModel.Proto;
})(ThingModel || (ThingModel = {}));
var ThingModel;
(function (ThingModel) {
(function (Proto) {
var ProtoTools = (function () {
function ProtoTools() {
}
ProtoTools.Builder = dcodeIO.ProtoBuf.loadJson({ "package": "ThingModel.Proto", "messages": [{ "name": "Property", "fields": [{ "rule": "required", "type": "int32", "name": "string_key", "id": 1, "options": {} }, { "rule": "required", "type": "Type", "name": "type", "id": 2, "options": { "default": "STRING" } }, { "rule": "optional", "type": "Location", "name": "location_value", "id": 3, "options": {} }, { "rule": "optional", "type": "String", "name": "string_value", "id": 4, "options": {} }, { "rule": "optional", "type": "double", "name": "double_value", "id": 5, "options": {} }, { "rule": "optional", "type": "sint32", "name": "int_value", "id": 6, "options": {} }, { "rule": "optional", "type": "bool", "name": "boolean_value", "id": 7, "options": {} }, { "rule": "optional", "type": "int64", "name": "datetime_value", "id": 8, "options": {} }], "enums": [{ "name": "Type", "values": [{ "name": "LOCATION_POINT", "id": 0 }, { "name": "LOCATION_LATLNG", "id": 1 }, { "name": "LOCATION_EQUATORIAL", "id": 2 }, { "name": "STRING", "id": 3 }, { "name": "DOUBLE", "id": 4 }, { "name": "INT", "id": 5 }, { "name": "BOOLEAN", "id": 6 }, { "name": "DATETIME", "id": 7 }], "options": {} }], "messages": [{ "name": "Location", "fields": [{ "rule": "required", "type": "double", "name": "x", "id": 1, "options": { "default": 0 } }, { "rule": "required", "type": "double", "name": "y", "id": 2, "options": { "default": 0 } }, { "rule": "optional", "type": "double", "name": "z", "id": 3, "options": { "default": 0 } }, { "rule": "optional", "type": "int32", "name": "string_system", "id": 4, "options": {} }, { "rule": "optional", "type": "bool", "name": "z_null", "id": 5, "options": { "default": false } }], "enums": [], "messages": [], "options": {} }, { "name": "String", "fields": [{ "rule": "optional", "type": "string", "name": "value", "id": 1, "options": {} }, { "rule": "optional", "type": "int32", "name": "string_value", "id": 2, "options": { "default": 0 } }], "enums": [], "messages": [], "options": {} }], "options": {} }, { "name": "PropertyType", "fields": [{ "rule": "required", "type": "int32", "name": "string_key", "id": 1, "options": {} }, { "rule": "required", "type": "Type", "name": "type", "id": 2, "options": { "default": "STRING" } }, { "rule": "required", "type": "bool", "name": "required", "id": 3, "options": { "default": true } }, { "rule": "optional", "type": "int32", "name": "string_name", "id": 4, "options": {} }, { "rule": "optional", "type": "int32", "name": "string_description", "id": 5, "options": {} }], "enums": [{ "name": "Type", "values": [{ "name": "LOCATION", "id": 0 }, { "name": "STRING", "id": 1 }, { "name": "DOUBLE", "id": 2 }, { "name": "INT", "id": 3 }, { "name": "BOOLEAN", "id": 4 }, { "name": "DATETIME", "id": 5 }], "options": {} }], "messages": [], "options": {} }, { "name": "StringDeclaration", "fields": [{ "rule": "required", "type": "string", "name": "value", "id": 1, "options": {} }, { "rule": "required", "type": "int32", "name": "key", "id": 2, "options": {} }], "enums": [], "messages": [], "options": {} }, { "name": "Thing", "fields": [{ "rule": "required", "type": "int32", "name": "string_id", "id": 1 }, { "rule": "required", "type": "int32", "name": "string_type_name", "id": 2 }, { "rule": "repeated", "type": "Property", "name": "properties", "id": 3 }, { "rule": "repeated", "type": "int32", "name": "connections", "id": 4, "options": { "packed": true } }, { "rule": "optional", "type": "bool", "name": "connections_change", "id": 5, "options": { "default": false } }], "enums": [], "messages": [] }, { "name": "ThingType", "fields": [{ "rule": "required", "type": "int32", "name": "string_name", "id": 1 }, { "rule": "optional", "type": "int32", "name": "string_description", "id": 2 }, { "rule": "repeated", "type": "PropertyType", "name": "properties", "id": 3 }], "enums": [], "messages": [] }, { "name": "Transaction", "fields": [{ "rule": "repeated", "type": "StringDeclaration", "name": "string_declarations", "id": 1 }, { "rule": "repeated", "type": "Thing", "name": "things_publish_list", "id": 2 }, { "rule": "repeated", "type": "int32", "name": "things_remove_list", "id": 3, "options": { "packed": true } }, { "rule": "repeated", "type": "ThingType", "name": "thingtypes_declaration_list", "id": 4 }, { "rule": "required", "type": "int32", "name": "string_sender_id", "id": 5 }], "enums": [], "messages": [] }], "enums": [], "imports": [], "services": [] }).build("ThingModel.Proto");
return ProtoTools;
})();
Proto.ProtoTools = ProtoTools;
})(ThingModel.Proto || (ThingModel.Proto = {}));
var Proto = ThingModel.Proto;
})(ThingModel || (ThingModel = {}));
var ThingModel;
(function (ThingModel) {
(function (Proto) {
var ToProtobuf = (function () {
function ToProtobuf() {
this.StringDeclarations = {};
this.StringDeclarationsCpt = 0;
this._stringToDeclare = {};
this._thingsState = {};
this._propertiesState = {};
}
ToProtobuf.prototype.StringToKey = function (value) {
if (!value) {
return 0;
}
var key = this.StringDeclarations[value];
if (key) {
return key;
}
key = ++this.StringDeclarationsCpt;
this.StringDeclarations[value] = key;
var stringDeclaration = new Proto.ProtoTools.Builder.StringDeclaration();
stringDeclaration.setKey(key);
stringDeclaration.setValue(value);
this._transaction.string_declarations.push(stringDeclaration);
return key;
};
ToProtobuf.prototype.Convert = function (publish, deletions, declarations, senderID) {
var _this = this;
this._transaction = new Proto.ProtoTools.Builder.Transaction();
this._transaction.setStringSenderId(this.StringToKey(senderID));
_.each(publish, function (thing) {
_this.ConvertThing(thing);
});
this.ConvertDeleteList(deletions);
this.ConvertDeclarationList(declarations);
return this._transaction;
};
ToProtobuf.prototype.ConvertTransaction = function (transaction) {
return transaction.toArrayBuffer();
};
ToProtobuf.prototype.ConvertThing = function (thing) {
var _this = this;
var change = false;
var thingID = this.StringToKey(thing.ID);
var publication = new Proto.ProtoTools.Builder.Thing();
publication.setStringId(thingID);
publication.setStringTypeName(thing.Type != null ? this.StringToKey(thing.Type.Name) : 0);
publication.setConnectionsChange(false);
var previousThing = this._thingsState[thingID];
if (previousThing == null || previousThing.getStringTypeName() != publication.getStringTypeName()) {
change = true;
}
var connectedThingsCache = null;
if ((previousThing == null && thing.ConnectedThingsCount > 0) || (previousThing != null && previousThing.getConnections().length != thing.ConnectedThingsCount)) {
publication.setConnectionsChange(true);
} else {
connectedThingsCache = thing.ConnectedThings;
_.any(connectedThingsCache, function (connectedThing) {
var connectionKey = _this.StringToKey(connectedThing.ID);
if (previousThing == null || !_.contains(previousThing.getConnections(), connectionKey)) {
publication.setConnectionsChange(true);
return true;
}
return false;
});
}
if (publication.getConnectionsChange()) {
change = true;
if (!connectedThingsCache) {
connectedThingsCache = thing.ConnectedThings;
}
_.each(connectedThingsCache, function (connectedThing) {
var connectionKey = _this.StringToKey(connectedThing.ID);
publication.connections.push(connectionKey);
});
}
_.each(thing.Properties, function (property) {
var propertyId = _this.StringToKey(property.Key);
var proto = new Proto.ProtoTools.Builder.Property();
proto.setStringKey(propertyId);
switch (property.Type) {
case 3 /* LocationLatLng */:
case 2 /* LocationPoint */:
case 4 /* LocationEquatorial */:
_this.ConvertLocationProperty(property, proto);
break;
case 5 /* String */:
_this.ConvertStringProperty(property, proto);
break;
case 6 /* Double */:
proto.setType(4 /* DOUBLE */);
proto.setDoubleValue(property.Value);
break;
case 7 /* Int */:
proto.setType(5 /* INT */);
proto.setIntValue(property.Value);
break;
case 8 /* Boolean */:
proto.setType(6 /* BOOLEAN */);
proto.setBooleanValue(property.Value);
break;
case 9 /* DateTime */:
proto.setType(7 /* DATETIME */);
proto.setDatetimeValue(property.Value.getTime());
break;
}
var propertyStateKey = thingID + ":" + propertyId;
if (previousThing != null) {
var previousProto = _this._propertiesState[propertyStateKey];
if (previousProto != null && previousProto.getType() == proto.getType() && previousProto.getBooleanValue() == proto.getBooleanValue() && previousProto.getDatetimeValue() == proto.getDatetimeValue() && previousProto.getDoubleValue() == proto.getDoubleValue() && previousProto.getIntValue() == proto.getIntValue()) {
var previousLoc = previousProto.getLocationValue();
var loc = proto.getLocationValue();
if ((previousLoc == null && loc == null) || (previousLoc != null && loc != null && previousLoc.x == loc.x && previousLoc.y == loc.y && previousLoc.z == loc.z && previousLoc.z_null == loc.z_null && previousLoc.getStringSystem() == loc.getStringSystem())) {
var previousStr = previousProto.getStringValue();
var str = proto.getStringValue();
if ((previousStr == null && str == null) || (previousStr != null && str != null && ((previousStr.getStringValue() == str.getStringValue() && previousStr.getValue() == str.getValue()) || (property.ValueToString() == previousStr.getValue())))) {
return;
}
}
}
}
change = true;
publication.properties.push(proto);
_this._propertiesState[propertyStateKey] = proto;
});
if (change) {
this._transaction.things_publish_list.push(publication);
this._thingsState[thingID] = publication;
}
};
ToProtobuf.prototype.ConvertDeleteList = function (list) {
var _this = this;
_.each(list, function (thing) {
var key = _this.StringToKey(thing.ID);
_this._transaction.things_remove_list.push(key);
_this.ManageThingSuppression(key);
});
};
ToProtobuf.prototype.ConvertDeclarationList = function (list) {
var _this = this;
_.each(list, function (thingType) {
var declaration = new Proto.ProtoTools.Builder.ThingType();
declaration.setStringName(_this.StringToKey(thingType.Name));
declaration.setStringDescription(_this.StringToKey(thingType.Description));
_.each(thingType.Properties, function (propertyType) {
var prop = new Proto.ProtoTools.Builder.PropertyType();
prop.setStringKey(_this.StringToKey(propertyType.Key));
prop.setStringName(_this.StringToKey(propertyType.Name));
prop.setStringDescription(_this.StringToKey(propertyType.Description));
prop.setRequired(propertyType.Required);
switch (propertyType.Type) {
case 3 /* LocationLatLng */:
case 4 /* LocationEquatorial */:
case 2 /* LocationPoint */:
case 1 /* Location */:
prop.setType(0 /* LOCATION */);
break;
case 5 /* String */:
prop.setType(1 /* STRING */);
break;
case 6 /* Double */:
prop.setType(2 /* DOUBLE */);
break;
case 7 /* Int */:
prop.setType(3 /* INT */);
break;
case 8 /* Boolean */:
prop.setType(4 /* BOOLEAN */);
break;
case 9 /* DateTime */:
prop.setType(5 /* DATETIME */);
break;
}
declaration.properties.push(prop);
});
_this._transaction.thingtypes_declaration_list.push(declaration);
});
};
ToProtobuf.prototype.ConvertLocationProperty = function (property, proto) {
var value = property.Value;
switch (value.type) {
case "latlng":
proto.setType(1 /* LOCATION_LATLNG */);
break;
case "equatorial":
proto.setType(2 /* LOCATION_EQUATORIAL */);
break;
case "point":
default:
proto.setType(0 /* LOCATION_POINT */);
break;
}
var loc = new Proto.ProtoTools.Builder.Property.Location();
loc.setX(value.X);
loc.setY(value.Y);
loc.setStringSystem(this.StringToKey(value.System));
loc.setZNull(value.Z == null);
if (value.Z != null) {
loc.setZ(value.Z);
}
proto.setLocationValue(loc);
};
ToProtobuf.prototype.ConvertStringProperty = function (property, proto) {
var value = property.Value;
proto.setType(3 /* STRING */);
var st = new Proto.ProtoTools.Builder.Property.String();
if (value && this._stringToDeclare[value]) {
st.setStringValue(this.StringToKey(value));
} else {
st.setValue(value);
this._stringToDeclare[value] = true;
}
proto.setStringValue(st);
};
ToProtobuf.prototype.ManageThingSuppression = function (thingId) {
var _this = this;
delete this._thingsState[thingId];
var stringId = thingId + ":";
_.each(this._propertiesState, function (value, key) {
if (key.indexOf(stringId) === 0) {
delete _this._propertiesState[key];
}
});
};
ToProtobuf.prototype.ApplyThingsSuppressions = function (things) {
var _this = this;
_.each(things, function (thing) {
var key = _this.StringDeclarations[thing.ID];
if (key) {
_this.ManageThingSuppression(key);
}
});
};
return ToProtobuf;
})();
Proto.ToProtobuf = ToProtobuf;
})(ThingModel.Proto || (ThingModel.Proto = {}));
var Proto = ThingModel.Proto;
})(ThingModel || (ThingModel = {}));
var ThingModel;
(function (ThingModel) {
(function (Location) {
var Point = (function () {
function Point(x, y, z) {
if (typeof x === "undefined") { x = 0.0; }
if (typeof y === "undefined") { y = 0.0; }
if (typeof z === "undefined") { z = null; }
this.X = x;
this.Y = y;
this.Z = z;
this.type = "point";
}
Point.prototype.Compare = function (other) {
return other != null && other.X === this.X && other.Y === this.Y && other.Z == this.Z && other.System == this.System;
};
Point.prototype.toString = function () {
var s = this.X + " - " + this.Y;
if (this.Z != null) {
s += " - " + this.Z;
}
if (this.System != null) {
s += " -- " + this.System;
}
return s;
};
return Point;
})();
Location.Point = Point;
var LatLng = (function (_super) {
__extends(LatLng, _super);
function LatLng(latitude, longitude, altitude) {
if (typeof latitude === "undefined") { latitude = 0.0; }
if (typeof longitude === "undefined") { longitude = 0.0; }
if (typeof altitude === "undefined") { altitude = null; }
_super.call(this, latitude, longitude, altitude);
this.type = "latlng";
}
Object.defineProperty(LatLng.prototype, "Latitude", {
get: function () {
return this.X;
},
set: function (latitude) {
this.X = latitude;
},
enumerable: true,
configurable: true
});
Object.defineProperty(LatLng.prototype, "Longitude", {
get: function () {
return this.Y;
},
set: function (longitude) {
this.Y = longitude;
},
enumerable: true,
configurable: true
});
Object.defineProperty(LatLng.prototype, "Altitude", {
get: function () {
return this.Z;
},
set: function (altitude) {
this.Z = altitude;
},
enumerable: true,
configurable: true
});
return LatLng;
})(Point);
Location.LatLng = LatLng;
var Equatorial = (function (_super) {
__extends(Equatorial, _super);