главный модуль для работы с графами объектов FireFly и метаданными TypeDef зависимости: static-eval, uuid и @turf/boolean-point-in-polygon
var {v4: uuid} = require('uuid');
// загрузка в браузер:
// <script src="lib/polyfill.min.js"></script>
// <script src="lib/miscutils.js"></script>
// <script src="lib/supergraph.js"></script>
// загрузка в исходнике нода integra-node-red:
// var { global } = this.context()
// var { isEmpty, flatten } = global.get('miscutils')
// var { queryPath, blankObject } = global.get('supergraph')
// загрузка в function ноде integra-node-red:
// var {randomElem} = global.get('miscutils')
// var { queryPath } = global.get('supergraph')
// загрузка в nodejs:
require("babel-polyfill")
Object.assign(global, require('./miscutils.js'))
Object.assign(global, require('./supergraph.js'))
'ok'
miscutils-api miscutils v1.44 static-eval-api static-eval v1.17 GRAPH-LOAD-API GRAPH-CHANGE-API GRAPH-PATH-API FIELDS-SELECTION-API TYPEDEF-UTILS supergraph.js v1.62
'ok'
getBase getType getEntity isItem isPin isLink isEvent getName getPosition nameOrId hasType hasTypeFrom graphContains blankObject loadGraph unloadGraph loadChanges isType getEnclosedText getCondition getExpression queryPolygon queryPath queryTree selectFields getTemplate updateTemplate
typedef compareTypeDefVersions queryEntityTypes queryEntityHeirs queryEntityDef queryPinItems queryPinLinks objectToChanges objectsToChanges graphToChanges changesToGraph
возвращает базовый тип объекта FireFly, т.е. первую строку в списке типов types
[ getBase({ types: ['Item', 'IpVideoCamera'] }), getBase({}), getBase(null) ]
[ 'Item', undefined, undefined ]
возвращает собственный тип объекта FireFly, т.е. вторую строку в списке типов types
[ getType({ types: ['Item', 'IpVideoCamera'] }), getType({}), getBase(null) ]
[ 'IpVideoCamera', undefined, undefined ]
возвращает сущность объекта FireFly, т.е. базовый тип строчными буквами
[ getEntity({ types: ['Item', 'IpVideoCamera'] }), getEntity({}), getBase(null) ]
[ 'item', undefined, undefined ]
проверяет является ли объект датчиком (итемом)
[isItem({ types: ['Item', 'IpVideoCamera' ] }),
isItem({ types: ['Pin', 'LogicInputPin' ] }),
isItem({ types: ['Link', 'LogicLink' ] }),
isItem({ types: ['Event', 'StateEvent' ] })]
[ true, false, false, false ]
проверяет является ли объект разъемом (пином)
[isPin({ types: ['Item', 'IpVideoCamera' ] }),
isPin({ types: ['Pin', 'LogicInputPin' ] }),
isPin({ types: ['Link', 'LogicLink' ] }),
isPin({ types: ['Event', 'StateEvent' ] })]
[ false, true, false, false ]
проверяет является ли объект связью (линком)
[isLink({ types: ['Item', 'IpVideoCamera' ] }),
isLink({ types: ['Pin', 'LogicInputPin' ] }),
isLink({ types: ['Link', 'LogicLink' ] }),
isLink({ types: ['Event', 'StateEvent' ] })]
[ false, false, true, false ]
проверяет является ли объект событием (эвентом)
[isEvent({ types: ['Item', 'IpVideoCamera' ] }),
isEvent({ types: ['Pin', 'LogicInputPin' ] }),
isEvent({ types: ['Link', 'LogicLink' ] }),
isEvent({ types: ['Event', 'StateEvent' ] })]
[ false, false, false, true ]
возвращает имя объекта т.е. значение ключевого параметра name
getName({ params: { name: { value: 'Датчик1' } } })
'Датчик1'
возвращает позицию объекта т.е. значение ключевого параметра position
getPosition({ params: { position: { value: 'POINT(50.22208228 53.2362814)' } } })
[ 50.22208228, 53.2362814 ]
возвращает имя или идентификатор объекта, если имя не указано
[nameOrId({ id: 'ID1', name: 'Name1' }),
nameOrId({ id: 'ID2' })]
[ 'Name1', 'ID2' ]
возвращает функцию проверки типа объектов FireFly
var isStateEvent = hasType('StateEvent');
[isStateEvent({ types: ['Event', 'ZoneEvent' ] }),
isStateEvent({ types: ['Event', 'StateEvent' ] })]
[ false, true ]
возвращает функцию проверки вхождения типа объектов в список типов FireFly
var isVideoCameraOrSensor = hasTypeFrom(['VideoCamera','Sensor']);
[isVideoCameraOrSensor({ types: ['Item', 'Zone' ] }),
isVideoCameraOrSensor({ types: ['Item', 'Sensor' ] })]
[ false, true ]
загружает граф FireFly в суперграф в памяти
loadGraph('cc467016-e940-4ce6-a5be-b14c9da2947f', { items: {}, links: {} })
вызагружает граф FireFly из суперграфа в памяти
unloadGraph('cc467016-e940-4ce6-a5be-b14c9da2947f')
проверяет, что аргумент является элементом графа, т.е. что имеет валидный тип и содержится в текущей копии суперграфа в памяти
var serverId = 'cc467016-e940-4ce6-a5be-b14c9da2947f';
var obj = {
id: '3998b9c7-0d56-4863-9633-7bec609aaf9a',
types: ['Item', 'IpVideoCamera' ],
params: {
name: { value: 'Камера1' }
}
};
var graph = {
items: { [obj.id]: obj },
links: {},
};
console.log(graphContains(obj),graphContains({}),graphContains(null))
loadGraph(serverId, graph); console.log(graphContains(obj));
unloadGraph(serverId, graph); console.log(graphContains(obj));
false false false true false
создает пустой объект FireFly при помощи, которого можно получить пакеты, которые следует отправить на сервер, для фактического создания объекта
var blank = blankObject('cc467016-e940-4ce6-a5be-b14c9da2947f', 'item');
var updates = [
blank.update('type', 'IpVideoCamera'),
blank.update('name', 'Камера1'),
];
console.log(JSON.stringify(updates,null,2))
[
{
"operation": "create",
"entity": "item",
"server": "cc467016-e940-4ce6-a5be-b14c9da2947f",
"owner": "cc467016-e940-4ce6-a5be-b14c9da2947f",
"id": "a7ec22aa-7b48-4da6-96cb-eaa324feb41e",
"params": {
"type": {
"value": "IpVideoCamera"
}
},
"datetime": 0
},
{
"operation": "update",
"entity": "item",
"server": "cc467016-e940-4ce6-a5be-b14c9da2947f",
"owner": "cc467016-e940-4ce6-a5be-b14c9da2947f",
"id": "a7ec22aa-7b48-4da6-96cb-eaa324feb41e",
"params": {
"name": {
"value": "Камера1"
}
},
"datetime": 0
}
]
загружает пакеты с изменениями графа FireFly
loadGraph(serverId, graph);
console.log(getName(obj), getPosition(obj), graphContains(obj));
var changes = [{
operation: 'update',
entity: 'item',
server: 'cc467016-e940-4ce6-a5be-b14c9da2947f',
owner: 'cc467016-e940-4ce6-a5be-b14c9da2947f',
id: '3998b9c7-0d56-4863-9633-7bec609aaf9a',
name: 'name',
value: 'Камера2',
datetime: epochtime()
},{
operation: 'update',
entity: 'item',
server: 'cc467016-e940-4ce6-a5be-b14c9da2947f',
owner: 'cc467016-e940-4ce6-a5be-b14c9da2947f',
id: '3998b9c7-0d56-4863-9633-7bec609aaf9a',
name: 'position',
value: 'POINT(50.22205734252930 53.23633956909180)',
datetime: epochtime()
}];
loadChanges(changes);
console.log(getName(obj), getPosition(obj), graphContains(obj));
Камера1 [] true Камера2 [ 50.2220573425293, 53.2363395690918 ] true
проверяет что аргументя является валидным идентификатором и начинается с заглавной буквы, т.к. только так могут выглядеть имена типов объектов FireFly
[ isType(1), isType('item'), isType('Item'), isType('IpVideoCamera1') ]
[ false, false, true, true ]
создает функцию достающую из переданного ей аргумента текст ограниченый сначала и с конца указанными строками, т.е. например проверяет, что текст обрамлен скобками и возвращает этот текст
console.log(getEnclosedText('(',')')('(123)'))
console.log(getEnclosedText('(',')')(' 123 '))
123 undefined
проверяет, что переданный аргумент начинается с ?( и заканчивается ), а затем пытается скомпилировать текст посередине как выражение static-eval, и в случае успеха возвращает полученную функцию
var f = getCondition('?(x % 2 == True)');
f({ x: 123 })
false
проверяет, что переданный аргумент начинается с ( и заканчивается ), а затем пытается скомпилировать текст посередине как выражение static-eval, и в случае успеха возвращает полученную функцию
var f = getExpression('(x+1)');
f({ x: 123 })
124
функция для поиска элементов в графе находящихся внутри заданного полигона при помощи @turf/boolean-point-in-polygon
var area = 'POLYGON((50.22205734252930 53.23633956909180,50.22212782475368 53.23635106308247,50.22213308362630 53.23633408754193,50.22205542015872 53.23632573239626,50.22205734252930 53.23633956909180))';
var polygon = parsePolygon(area);
var items = queryPolygon(polygon);
console.log(items);
[
{
id: '3998b9c7-0d56-4863-9633-7bec609aaf9a',
types: [ 'Item', 'IpVideoCamera' ],
params: { name: [Object], position: [Object] },
serverId: 'cc467016-e940-4ce6-a5be-b14c9da2947f',
pins: {},
name: 'Камера2',
position: [ 50.2220573425293, 53.2363395690918 ],
search: [Function: queryPath],
update: [Function (anonymous)],
delete: [Function (anonymous)],
get: [Function (anonymous)],
refs: [Function (anonymous)],
ref: [Function (anonymous)],
parse: [Function (anonymous)],
eval: [Function (anonymous)],
time: 1662550230.95
}
]
Функция для поиска элементов в графе при помощи строки специального формата, первым аргументом функция принимает эту строку, а вторым список исходных элементов (если список пуст, то поиск происходит по всему графу).
Строка поиска связанных элементов состоит из набора команд разделенных символом /.
При этом каждая команда состоит из альтернатив разделенных символом |.
Механизм поиска связанных элементов по заданному элементу представляет собой конечный автомат, со следующими состояниями:
- Тип разъема - выбрать в графе все разъемы указанного типа.
- Тип связи - выбрать в графе все связи указанного типа.
- Тип элемента - выбрать в графе все элементы указанного типа.
- Идентификатор элемента - выбрать в графе элемент с заданным идентификатором (идентификатор строго уникален).
- Имя элемента - выбрать в графе элемент с заданным именем (за уникальностью имени должно следить клиентское приложение).
- Имя параметра - считать из параметра имя элемента, идентификатор или список идентификаторов элементов и перейти в них.
- Имя разъема - перейти в указанный разъем на данном элементе.
- Тип разъема - перейти во все разъемы указанного типа на данном элементе.
- Тип связи - перейти во все связи указанного типа соединяющие разъем данного элемента.
- Тип устройства - остаться в текущем устройстве, если его тип совместим с указанным, иначе остановить поиск.
- Все тоже что и Item, т.к. является его наследником.
- Имя класса - если данный экземпляр в иерархии наследования имеет предком указанный класс, то остаться в нем, иначе остановить поиск.
- Имя параметра - считать из параметра имя элемента, идентификатор или список идентификаторов элементов и перейти в них.
- Тип разъема - перейти в разъемы указанного типа, находящиеся на противоположной стороне от разъема, по которому алгоритм попал в данную связь.
- Тип устройства - перейти в устройство указанного типа соединенного с противоположным концом данной связи.
- Тип связи - остаться в текущей связи, если её тип совместим с указанным, иначе остановить поиск.
- Имя параметра - считать из параметра имя элемента, идентификатор или список идентификаторов элементов и перейти в них.
- Тип устройства - перейти в устройство указанного типа соединенного с противоположным концом связи этого разъема.
- Тип связи - перейти во все связи указанного типа, присоединенные к данному разъему.
- Имя параметра - считать из параметра имя элемента, идентификатор или список идентификаторов элементов и перейти в них.
- Тип события - остаться в текущем событии, если его тип совместим с указанным, иначе остановить поиск.
Результат полученный по всем альтернативным веткам команды объединяется и выравнивается в плоский список.
Если по команде ничего не найдено, поиск по этой ветке останавливается.
Источником или корнем для следующей команды становятся все результаты полученные на предыдущем этапе.
Каждая команда так же может быть условием написанным с помощью безопасно-вычислимых выражений static-eval, заключенной между символами ? и ).
Computer/?(params.cpu_usage < 50)
Computer/(params.cpu_usage/100)
Computer/2
Computer/1
Наконец возможен поиск подграфа при помощи многострочной строки поиска, где отступ от предыдущей строчки указывает на то, что поиск следует начинать от предыдущего результата. В примере первая строчка ищется по всему графу. Вторая от результата первой. Третья тоже от результата первой, т. к. отступ не увеличился. Четвертая ищется от результата третьей, а пятая соответственно от четвертой. Результатом queryPath будет массив элементов, где каждый элемент содержит результат поиска строки с соответствующим индексом.
ImportSource/1
LogicLink/Binding/?(cron)/1
ImportLink/Import
classes/Class
/Instance/?($name in classes)/2
"VideoCamera"
"!VideoCamera"
"2c5a5d58-5d04-4325-81c6-830a0661bb41/VideoCamera"
"Какая-то видеокамера/VideoCamera"
"1b63a2bd-733d-4788-9fb1-c987335eafcf|f62fe1da-a563-4c90-b13c-3d9eb95a5573/Space/Pin/VideoCamera"
"logicOutput/VideoCamera"
"Pin/Space/Pin/VideoCamera"
"owner/Zone/Pin/VideoCamera"
"trace_zones/Zone/Pin/VideoCamera"
"Link/Space|Zone/Link/LowCurrentSirenMeta"
"Computer/?(cpu_usage > 50)"
"Computer/?(cpu_usage > 50)/(cpu_usage)/1"
var multipath = `
ImportSource/1
LogicLink/Binding/?(cron)/1
ImportLink/Import
classes/Class
/Instance/?($name in classes)/2`;
var [source,binding,imports,classes,instances] = queryPath(multipath);
var camera = queryPath('IpVideoCamera/1');
camera
{
id: '3998b9c7-0d56-4863-9633-7bec609aaf9a',
types: [ 'Item', 'IpVideoCamera' ],
params: {
name: {
value: 'Камера2',
datetime: 1662550230.95,
status: undefined,
version: undefined
},
position: {
value: 'POINT(50.22205734252930 53.23633956909180)',
datetime: 1662550230.95,
status: undefined,
version: undefined
}
},
serverId: 'cc467016-e940-4ce6-a5be-b14c9da2947f',
pins: {},
name: 'Камера2',
position: [ 50.2220573425293, 53.2363395690918 ],
search: [Function: queryPath],
update: [Function (anonymous)],
delete: [Function (anonymous)],
get: [Function (anonymous)],
refs: [Function (anonymous)],
ref: [Function (anonymous)],
parse: [Function (anonymous)],
eval: [Function (anonymous)],
time: 1662550230.95
}
var types = queryPath(`BaseObject/(types[1]+' '+name)`);
console.log(types.length, types);
var types = queryPath(`BaseObject/?(name)/(types[1]+' '+name)`);
console.log(types.length, types);
var types = queryPath(`BaseObject/!Plane/!Female/!Zone/!Sensor/(types[1]+' '+name)`);
console.log(types.length, types);
var types = queryPath(`BaseObject/Plane|Female|Zone|Sensor/(types[1]+' '+name)`);
console.log(types.length, types);
13 [ 'EnvMonitoringSubstanceSensor ', 'EnvMonitoringWeatherSensor ', 'IpVideoCamera Камера 109', 'EnvMonitoringPost ', 'Female Chica Flaca', 'Plane Самолет 1', 'Zone test143', 'Zone Площадка за офисом', 'BOLID_FireSensor BOLID_FireSensor1', 'IpPTZVideoCamera PTZ Cam 211', 'Zone Площадка перед складом-гаражом', 'Zone Парковка и терасса (211)', 'EnvMonitoringChimneyPost ' ] 9 [ 'IpVideoCamera Камера 109', 'Female Chica Flaca', 'Plane Самолет 1', 'Zone test143', 'Zone Площадка за офисом', 'BOLID_FireSensor BOLID_FireSensor1', 'IpPTZVideoCamera PTZ Cam 211', 'Zone Площадка перед складом-гаражом', 'Zone Парковка и терасса (211)' ] 5 [ 'EnvMonitoringSubstanceSensor ', 'IpVideoCamera Камера 109', 'EnvMonitoringPost ', 'IpPTZVideoCamera PTZ Cam 211', 'EnvMonitoringChimneyPost ' ] 8 [ 'Plane Самолет 1', 'Female Chica Flaca', 'Zone test143', 'Zone Площадка за офисом', 'Zone Площадка перед складом-гаражом', 'Zone Парковка и терасса (211)', 'EnvMonitoringWeatherSensor ', 'BOLID_FireSensor BOLID_FireSensor1' ]
Функция для поиска всех объектов соединенных с заданными на любом уровне дерева, т.е. всего поддерева, в которое входят заданные объеты. На каждом уровне поддерева для поиска используется указаный путь.
var am = randomElem(queryPath('AcuarioManager'));
console.log(getType(am), am.name)
var objs = queryTree('Link/Item', [am])
console.log(objs.length)
for(var obj of objs) console.log(getType(obj), obj.name||obj.id);
AcuarioManager 3 AcuarioManager 02658aa6-d40f-4b30-92df-0ee3f392d5b4 Server 54103689-170d-4ec6-8f7e-4f4917ad671f IntegraVideo7 d48951f6-1f7c-462d-a595-ceec424bf35e
функция делающая выборку из javascript объекта по заданному шаблону или его зарегистрированному имени
по умолчанию зарегистрированы следующие шаблоны:
copy - пытается скопировать всю структуру как есть, игнорируя однако любые повторы во избежании зацикливания (подходит для любых структур)deep - копирует основные атрибуты элемента в корень, а параметры и пины в соответствующие словари с сохранением структуры (подходит только для элементов графа)shallow - копирует основные атрибуты элемента в корень, параметры и пины так же копирует в корень с сохранением структуры (подходит только для элементов графа)flat - копирует основные атрибуты элемента в корень, так же копирует в корень значения параметров и пины (подходит только для элементов графа)const shallowTemplate = {
serverId: 'serverId',
id: 'id',
types: 'types',
params: { '*': '{*}' },
pins: {
'*': {
types: { 1 : '{*.type}' },
params: { '*': '{*.*}' },
links: {
'*' : {
in: { owner: { id: '[linkedItems]' } },
out: { owner: { id: '[linkedItems]' } },
}
},
}
}
};
ключи любого уровня в шаблоне повторяют структуру исходного объекта, т.е. как бы указывают путь к необходимым атрибутам, тогда как значения указывают путь в целевом объекте
если ключом является символ *, то выборку содержащуюся в его значении следует применить ко всем элементам родительского словаря
этот же символ в значении заменяется на соответствующее имя ключа словаря источника
params: { '*': '{*}' }
если атрибут копируется в корень целевого объекта, то в качестве значения достаточно указать имя целевого атрибута
serverId: 'serverId'
в фигурных скобках следует указывать путь к не корневому атрибуту целевого объекта
pins: {
'*': {
types: { 1 : '{*.type}' },
в данном случае для каждого пина, например logicInput, из принадлежащего ему массива типов types, выбирается второе значение (т.е. имя главного типа объекта), и записывается в целевой объект по пути logicInput.type
путь к целевому атрибуту в квадратных скобках говорит о том, что каждое встреченное значение по этому пути в объекте источнике будет добавлено к соответствующему массиву в целевом объекте
links: {
'*' : {
in: { owner: { id: '[linkedItems]' } },
var camera = queryPath('IpVideoCamera/1');
var template = 'copy';
var template = 'deep';
var template = 'shallow';
var template = 'flat';
var template = getTemplate('shallow');
var view = selectFields(template)(camera);
console.log(view);
{
serverId: 'cc467016-e940-4ce6-a5be-b14c9da2947f',
id: '3998b9c7-0d56-4863-9633-7bec609aaf9a',
types: [ 'Item', 'IpVideoCamera' ],
name: {
value: 'Камера2',
datetime: 1662550230.95,
status: undefined,
version: undefined
},
position: {
value: 'POINT(50.22205734252930 53.23633956909180)',
datetime: 1662550230.95,
status: undefined,
version: undefined
}
}
следующий пример показывает как при помощи выражений static-eval в тексте ключей шаблона можно изменить значение соответствующего ключа в результате
var obj = queryPath('IpVideoCamera/1')
var template1 = {
types: { 1: 'type' },
id: 'id',
params: {
name: { value: 'fio' },
'(Date(name.datetime))': 'fiodate',
}
};
selectFields(template1)(obj)
{
type: 'IpVideoCamera',
id: '3998b9c7-0d56-4863-9633-7bec609aaf9a',
fio: 'Камера2',
fiodate: 'Wed Sep 07 2022 11:31:02 GMT+0000 (Coordinated Universal Time)'
}
считывает текст именованного шаблона
var template = getTemplate('flat')
console.log(JSON.stringify(template,null,2))
{
"serverId": "serverId",
"id": "id",
"types": "types",
"params": {
"*": {
"value": "{*}"
}
},
"pins": {
"*": {
"types": {
"1": "{*.type}"
},
"params": {
"*": {
"value": "{*.*}"
}
},
"links": {
"*": {
"in": {
"owner": {
"id": "[linkedItems]"
}
},
"out": {
"owner": {
"id": "[linkedItems]"
}
}
}
}
}
}
}
добавляет новый именованый шаблон
console.log(getTemplate('template1'))
updateTemplate('template1',template1)
console.log(getTemplate('template1'))
undefined
{
types: { '1': 'type' },
id: 'id',
params: { name: { value: 'fio' }, '(Date(name.datetime))': 'fiodate' }
}
Типы элементов системы описываются на языке XML версии 1.0 с использованием utf-8 кодировки.
Считываются все xml файлы лежащие в каталоге typedef и объединяются в один большой документ, в котором могут присутствовать в произвольном количестве следующие теги:
Корневой элемент каждого файла описания может называться произвольно например root.
Любой тег может содержать дополнительные атрибуты доступные в режиме исполнения. Дополнительный атрибут может иметь любое имя не совпадающее с именами служебных атрибутов описанных ниже. Имена дополнительных атрибутов так же не могут совпадать с именами тегов.
Теги enum, item, link, pin и event описывают конкретные элементы системы и их тела могут содержать произвольное количество тегов is, указывающих базовый тип элемента.
Тег is может содержать следующие атрибуты:
Наследуемый тип получает все значения, параметры и разъемы базового.
Тег enum содержит следующие атрибуты:
Тело тега enum содержит один или несколько тегов value, являющихся описанием конкретного значения перечисления.
Тело тега value содержит текстовое представление значения с которым связан данный элемент перечисления.
Так же тег value может содержать дополнительные атрибуты, например, в случае описания состояния устройства, следующие:
Тег enum должен содержать один тег value не имеющий тела, который может содержать дополнительные атрибуты по умолчанию для всех значений не описанных в перечислении.
Теги item, link, pin и event описывают конкретные элементы системы и их тела могут содержать произвольное количество тегов param, описывающих параметры данного элемента.
Тег param может содержать следующие атрибуты:
- bool - булево значение bool;
- int - целое знаковое число int8;
- real - число с плавающей точкой float8;
- guid - глобальный уникальный идентификатор uuid;
- time - дата/время timestamp;
- span - интервал времени interval;
- text - строка text;
- ltree - ветка иерархического дерева ltree;
- list - список строк text[];
- vector - список чисел с плавающей точкой float8[];
- blob - бинарные данные bytea;
- json - документ типа json json;
- xml - документ типа xml xml;
- point - точка в пространстве point;
- polygon - полигон polygon;
- args - если связано с перечисляемым типом при помощи атрибута enum, то список уникальных значений этого перечисления, иначе просто список строк text[];
Следующие атрибуты указывают компилятору на необходимость автоматического создания вспомогательных параметров в данном типе, именем этих новых параметров будет являться имя текущего параметра плюс подчеркивание и имя соответствующего атрибута, а значением по умолчанию такого параметра будет значение соответствующего атрибута:
Если тип параметра не указан то считается что это текстовый параметр.
Тело тега param может содержать текстовое представление значения поля по умолчанию.
Экземпляр элемента системы может содержать только одну копию одного и того же параметра.
Имена параметров in и out являются частично зарезервированными и не должны использоваться при описании типов соединений. Имена параметров name, state и stateargs, так же является частично зарезервированными, но должны быть описаны для каждого типа устройства.
Состояние элемента определяется двумя параметрами:
Тег pin может содержать следующие атрибуты:
Тег link может содержать следующие атрибуты:
Тег item может содержать следующие атрибуты:
Тело тега item может содержать произвольное количество следующих тегов:
Тег pin может содержать следующие атрибуты:
Внутренний для устройства разъем не может содержать дополнительных параметров.
Тег event может содержать следующие атрибуты:
Тег schema может содержать следующие атрибуты:
Тело тега schema должно содержать валидную схему json документа.
В процессе парсинга первая буква всех имен типов переводится в верхний регистр, а первая буква всех имен параметров и разъемов в нижний.
Язык TypeDef позволяет описывать некий граф объектов и связи между ними, где основным элементом графа является item, который может иметь некоторое количество именованных разъемов pin, к которым в свою очередь могут быть подключены сзязи link. Таким образом элементы и item и link являются узлами графа и в конкретной реализации должны быть уникально идентифицируемы, тогда как pin идентифицируется своим владельцем item плюс своим уникальным именем. Элемент event так же должен быть уникально идентифицируем, однако не является узлом графа и сохраняется только в архиве изменений.
// загрузка типов в формате xml
const { JSDOM } = require("jsdom");
var xml = fs.readFileSync('typedef.xml');
var typedefXml = new JSDOM(xml, { contentType: 'text/xml' }).window.document;
// загрузка типов в формате json
var json = fs.readFileSync('typedef.json');
var typedefJson = JSON.parse(json);
сравнивает две версии формата {major}.{minor}.{build}.{revision}
в текущей реализации сравниваются только последние компоненты {revision}
[compareTypeDefVersions('0.0.0.1400', '0.0.0.1411'),
compareTypeDefVersions('0.0.0.1411', '0.0.0.1411'),
compareTypeDefVersions('0.0.0.1411', '0.0.0.1400')]
[ -11, 0, 11 ]
возвращает полный список типов заданной сущности
var types = queryEntityTypes(typedefJson, 'item')
console.log(types.length, types.slice(0,5), '...', types.slice(-5))
var types = queryEntityTypes(typedefXml, 'item')
console.log(types.length, types.slice(0,5), '...', types.slice(-5))
1122 [ 'AbstractComputer', 'AbstractTracker', 'AccessControlCategory', 'AccessController', 'AccessItem' ] ... [ 'Zonus', 'ZWaveDevice', 'ZWaveRelaySwitch', 'ZWaveServer', 'ZwaveSwitch' ] 1122 [ 'AbstractComputer', 'AbstractTracker', 'AccessControlCategory', 'AccessController', 'AccessItem' ] ... [ 'Zonus', 'ZWaveDevice', 'ZWaveRelaySwitch', 'ZWaveServer', 'ZwaveSwitch' ]
возвращает полный список наследников для заданного типа заданной сущности
var types = queryEntityHeirs(typedefJson, 'item', 'VideoCamera')
console.log(types.length, types)
var types = queryEntityHeirs(typedefXml, 'item', 'VideoCamera')
console.log(types.length, types)
8 [ 'AnalogPTZVideoCamera', 'AnalogVideoCamera', 'EmergencyCallPoint', 'IpPTZVideoCamera', 'IpSpeedCam', 'IpVideoCamera', 'IpVideoCameraCarCount', 'VideoTerminal' ] 8 [ 'AnalogPTZVideoCamera', 'AnalogVideoCamera', 'EmergencyCallPoint', 'IpPTZVideoCamera', 'IpSpeedCam', 'IpVideoCamera', 'IpVideoCameraCarCount', 'VideoTerminal' ]
возвращает описание заданого типа заданой сущности в json формате FireFly
var def = queryEntityDef(typedefJson, 'event', 'StateEvent')
console.log(def)
var def = queryEntityDef(typedefXml, 'event', 'StateEvent')
console.log(def)
{
attributes: { type: 'StateEvent' },
is: [ 'Event', 'StateEvent', 'BaseEvent', 'ProcessingEvent' ],
param: {
position: { attributes: [Object], default: null },
server: { attributes: [Object], default: null },
owner: { attributes: [Object], default: null },
event_status: { attributes: [Object], default: null },
user: { attributes: [Object], default: null },
event_comment: { attributes: [Object], default: null },
alarm_info: { attributes: [Object], default: null },
name: { attributes: [Object], default: null },
itemtype: { attributes: [Object], default: null },
version: { attributes: [Object], default: null },
datetime: { attributes: [Object], default: null },
state: { attributes: [Object], default: null }
}
}
{
attributes: { type: 'StateEvent' },
is: [ 'Event', 'StateEvent', 'BaseEvent', 'ProcessingEvent' ],
param: {
position: { attributes: [Object], default: null },
server: { attributes: [Object], default: null },
owner: { attributes: [Object], default: null },
event_status: { attributes: [Object], default: null },
user: { attributes: [Object], default: null },
event_comment: { attributes: [Object], default: null },
alarm_info: { attributes: [Object], default: null },
name: { attributes: [Object], default: null },
itemtype: { attributes: [Object], default: null },
version: { attributes: [Object], default: null },
datetime: { attributes: [Object], default: null },
state: { attributes: [Object], default: null }
}
}
возвращает список имен типов итемов которы могут быть соединены с заданым пином
console.log(queryPinItems(typedefJson, 'EgsInput'))
[ 'EgsOn', 'EgsOnCreate', 'EgsOnSchedule', 'EgsOnStart', 'EgsOnUpdate', 'EgsScenario', 'EgsScript', 'EgsTrigger' ]
возвращает список имен типов итемов которы могут быть соединены с заданым пином
console.log(queryPinLinks(typedefJson, 'EgsInput'))
[ 'EgsLink' ]
разбивает объект FireFly на массив пакетов при помощи которых этот объект можно создать
var obj = queryPath('/Item/1')
objectToChanges(obj)
[
{
operation: 'create',
entity: 'item',
server: 'cc467016-e940-4ce6-a5be-b14c9da2947f',
owner: 'cc467016-e940-4ce6-a5be-b14c9da2947f',
id: '3998b9c7-0d56-4863-9633-7bec609aaf9a',
datetime: 0,
type: 'IpVideoCamera',
types: [ 'Item', 'IpVideoCamera' ]
},
{
operation: 'update',
entity: 'item',
server: 'cc467016-e940-4ce6-a5be-b14c9da2947f',
owner: 'cc467016-e940-4ce6-a5be-b14c9da2947f',
id: '3998b9c7-0d56-4863-9633-7bec609aaf9a',
datetime: 0,
type: 'IpVideoCamera',
name: 'name',
value: 'Камера1'
}
]
разбивает список объектов FireFly на массив пакетов при помощи которых эти объекты можно создать
var obj = queryPath('/Item/1')
objectsToChanges([obj])
[
{
operation: 'create',
entity: 'item',
server: 'cc467016-e940-4ce6-a5be-b14c9da2947f',
owner: 'cc467016-e940-4ce6-a5be-b14c9da2947f',
id: '3998b9c7-0d56-4863-9633-7bec609aaf9a',
datetime: 0,
type: 'IpVideoCamera',
types: [ 'Item', 'IpVideoCamera' ]
},
{
operation: 'update',
entity: 'item',
server: 'cc467016-e940-4ce6-a5be-b14c9da2947f',
owner: 'cc467016-e940-4ce6-a5be-b14c9da2947f',
id: '3998b9c7-0d56-4863-9633-7bec609aaf9a',
datetime: 0,
type: 'IpVideoCamera',
name: 'name',
value: 'Камера1'
}
]
разбивает граф объектов FireFly на массив пакетов при помощи которых этот граф можно создать
graphToChanges(graph)
[
{
operation: 'create',
entity: 'item',
server: 'cc467016-e940-4ce6-a5be-b14c9da2947f',
owner: 'cc467016-e940-4ce6-a5be-b14c9da2947f',
id: '3998b9c7-0d56-4863-9633-7bec609aaf9a',
datetime: 0,
type: 'IpVideoCamera',
types: [ 'Item', 'IpVideoCamera' ]
},
{
operation: 'update',
entity: 'item',
server: 'cc467016-e940-4ce6-a5be-b14c9da2947f',
owner: 'cc467016-e940-4ce6-a5be-b14c9da2947f',
id: '3998b9c7-0d56-4863-9633-7bec609aaf9a',
datetime: 0,
type: 'IpVideoCamera',
name: 'name',
value: 'Камера1'
}
]
объендиняет массив пакетов с изменениями FireFly в графовую структуру
var changes = [{
operation: 'create',
entity: 'item',
server: 'cc467016-e940-4ce6-a5be-b14c9da2947f',
owner: 'cc467016-e940-4ce6-a5be-b14c9da2947f',
id: '3998b9c7-0d56-4863-9633-7bec609aaf9a',
type: 'IpVideoCamera',
datetime: epochtime()
},{
operation: 'update',
entity: 'item',
server: 'cc467016-e940-4ce6-a5be-b14c9da2947f',
owner: 'cc467016-e940-4ce6-a5be-b14c9da2947f',
id: '3998b9c7-0d56-4863-9633-7bec609aaf9a',
name: 'name',
value: 'Камера2',
datetime: epochtime()
}]
var graph = changesToGraph(changes)
console.log(JSON.stringify(graph,null,2))
{
"items": {
"3998b9c7-0d56-4863-9633-7bec609aaf9a": {
"params": {
"name": {
"value": "Камера2",
"datetime": 1662550295.729
}
},
"pins": {}
}
},
"links": {},
"version": 0
}
загрузим данные с реального сервера FireFly
Object.assign(global, require('./ffwamp.js'))
const WebSocket = require('ws');
const fetch = require('node-fetch');
var url = "ws://192.168.10.72:8301/ws";
var authorigin = 'http://62.69.14.245:10000/auth';
var authid = 'firefly';
var authpass = 'firefly';
async function run(callback=(async () => {})) {
var api = await connectToLocalServer(url, { authorigin, authid, authpass });
var { serverId, getGraph, changeGraph, goodbye } = api;
console.log('localServerId:', serverId);
try {
var json = await getGraph(serverId);
var graph = JSON.parse(json);
console.log('items:', Object.keys(graph.items).length);
console.log('links:', Object.keys(graph.links).length);
unloadGraph(serverId);
loadGraph(serverId, graph);
await callback(api);
}
catch(e) { throw e; }
finally { await goodbye(); }
}
run()
Promise { <pending> }
OUTPUT: [1,"integra-s",{"authmethods":["integra-db"],"roles":{"caller":{},"subscriber":{}}}]
INPUT: [4,"integra-db",{}]
OUTPUT: [5,"116daf9d-9d05-4215-ad16-894264ae26ab",{}]
INPUT: [2,8707605780785845,{"authrole":"firefly.user","authmethod":"integra-db","authprovider":"integra-s","roles":{"broker":{"features":{"publisher_identification":true,"publisher_exclusion":true,"subscriber_blackwhite_listing":true}},"dealer":{"features":{"pro...
OUTPUT: [48,12,{"disclose_me":true},"com.integra.ember.call_stored",["server.get",[0]],{}]
INPUT: [50,12,{},["{\"5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5\": {\"is_local\": true, \"status\": \"online\", \"position\": \"POINT(0 0)\", \"hash\": \"e2ba6b08-dc48-36d2-814a-af37201bdb38\", \"name\": \"Local server\", \"adm_level\": null, \"router_url\": \"localh...
localServerId: 5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5
OUTPUT: [48,13,{"disclose_me":true},"com.integra.ember.call_stored",["graph.get",["5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5",0]],{}]
INPUT: [50,13,{},["{\"graph_version\": 2498098, \"max_version\": 2498098, \"links\": {\"920e99d9-8449-457f-b2cc-9c2c7b04918b\": {\"params\": {\"out\": {\"version\": 2498098, \"value\": \"d79ec1a3-4ac1-4e37-916b-d59bbe8cfa2a.logicOutput\", \"datetime\": 166255044...
items: 37
links: 28
OUTPUT: [6,{},"wamp.close.goodbye_and_out"]
INPUT: [6,{},"wamp.goodbye.normal"]
(node:14058) UnhandledPromiseRejectionWarning: GOODBYE (node:14058) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 5)
каждый объект графа FireFly имеет так же набор удобных собственных функций
var toFlat = selectFields('flat');
var card = queryPath('Карточка1/1');
// поиск в графе при помощи queryPath, но начиная с владельца функции
console.log('search:', card.search('Link/Item').map(toFlat), '\n')
// создание пакета с изменением параметра
console.log('update:', card.update('state', 'alarm.alarm'), '\n')
// создание пакета с удалением владельца
console.log('delete:', card.delete(), '\n')
// безопасное получение параметра
console.log('get:', card.get('name').value, card.get('command').value, '\n')
// вызов выражения static-eval с владельцем функции в качестве контекста
console.log('eval:', card.eval('category+" "+name'), '\n')
// возвращает и кэширует javascript объект содержащийся в указаном параметре как json
// вторым аргументом parse можно указать специфический парсер, например parsePolygon
console.log('parse:', card.parse('regulations'), '\n')
// возвращает и кэширует FireFly объект идентификтор которого содержится в указаном параметре
console.log('ref:', toFlat(card.ref('value_250')), '\n')
console.log('refs:', card.refs('value_250').map(toFlat), '\n')
// проверить значение параметра функцией miscutils::areEqualValues
if(card.check('state', 'alarm.alarm')) {
}
search: [
{
serverId: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
id: '579f29ac-5b8a-4b0c-936c-7afe3e78d240',
types: [
'Item',
'IntegraAccidentCard',
'BaseObject',
'SpatialObject',
'BaseCardEvent'
],
incident_time: 1658926800,
name: 'qqq',
precedence: 50,
executors: [],
precedence_max: 100,
altitude: -65535,
time_created: 1658926800,
regulations: {
category: 'emergency_work',
executants: [],
regulations: [Object],
name: 'qqq',
areaColor: '#660000ff',
lists: [],
states: {},
complex: false,
interview: [Array],
showPolygon: true,
watching_services: [Array],
toDo: [],
additional: []
},
state: 'new_card',
deadline: 1658930400,
precedence_min: 0,
position: 'POINT(0 0)',
ignoreTimeout: 0,
watching_services: [ 1 ],
gpsContent: { type: 'GpsProviderIn' },
positionContent: { type: 'PositionContent' },
causeOf: { type: 'CauseOf' },
logicOutput: { type: 'LogicOutput' },
linkedItems: [
'7c20f7f3-84ba-4655-ae99-f452b1629a3f',
'579f29ac-5b8a-4b0c-936c-7afe3e78d240'
],
logicInput: { type: 'LogicInput' },
fileInput: { type: 'FileInput' },
provoker_input: { type: 'Provoker_input' },
person_input: { type: 'Person_input' },
imageInput: { type: 'ImageInput' }
}
]
update: {
operation: 'update',
entity: 'item',
server: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
owner: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
id: '7c20f7f3-84ba-4655-ae99-f452b1629a3f',
params: { state: { value: 'alarm.alarm' } },
datetime: 0
}
delete: {
operation: 'delete',
entity: 'item',
server: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
owner: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
id: '7c20f7f3-84ba-4655-ae99-f452b1629a3f',
datetime: 0
}
get: Карточка1 undefined
eval: emergency_work Карточка1
parse: { a: 1, b: 2 }
ref: {
serverId: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
id: '862c2a0d-c553-4dab-a720-f370802a03c1',
types: [ 'Item', 'Zone', 'BaseObject', 'SpatialObject' ],
global: true,
name: 'Зона 1',
precedence: 50,
is_water_zone: true,
precedence_max: 100,
altitude: -65535,
trace_factor: 1,
alarm_weight: 2,
state: 'ok.normal',
command: 'activate',
precedence_min: 0,
alarm_info: '{"alarm_factor":1,"alarm_precedence":0,"state_before":"alarm.alarm","state_after":"ok.normal","members":{"3d694a91-c6f8-423d-9c8b-17a005caf9b9":{"type":"IpPTZVideoCamera","state":"ok.normal","datetime":1659036334,"weight":1,"precedence":50,"importance":1,"alarm":false,"value":"ok.normal"},"b6c150c5-2402-4cbe-9730-a6fa3fdc2c83":{"type":"BOLID_VolumeSensor","state":"ok.normal","datetime":1659036337,"weight":1,"precedence":50,"importance":1,"alarm":false,"value":"ok.normal"},"af998922-1a8b-40af-afe9-c71b502bc018":{"type":"LowCurrentSirenMeta","weight":0,"precedence":50,"importance":1,"alarm":false},"cbfdb567-ea0f-4d24-b5db-9d135a467736":{"type":"StreetLighting","state":"ok.true","datetime":1659036328,"weight":0,"precedence":50,"importance":0,"alarm":false,"value":"ok.true"},"c2f58334-ebf4-4fff-b990-a7cae44ca463":{"type":"StreetLighting","state":"ok.true","datetime":1659036328,"weight":0,"precedence":50,"importance":0,"alarm":false,"value":"ok.true"}}}',
position: 'POINT(0 0)',
alarm_factor: 1,
ignoreTimeout: 0,
gpsContent: { type: 'GpsProviderIn' },
positionContent: { type: 'PositionContent' },
causeOf: { type: 'CauseOf' },
logicOutput: { type: 'LogicOutput' },
zoneOutputPin: { type: 'ZoneOutputPin' },
linkedItems: [
'3d694a91-c6f8-423d-9c8b-17a005caf9b9',
'862c2a0d-c553-4dab-a720-f370802a03c1',
'b6c150c5-2402-4cbe-9730-a6fa3fdc2c83',
'862c2a0d-c553-4dab-a720-f370802a03c1',
'af998922-1a8b-40af-afe9-c71b502bc018',
'862c2a0d-c553-4dab-a720-f370802a03c1',
'cbfdb567-ea0f-4d24-b5db-9d135a467736',
'862c2a0d-c553-4dab-a720-f370802a03c1',
'c2f58334-ebf4-4fff-b990-a7cae44ca463',
'862c2a0d-c553-4dab-a720-f370802a03c1'
],
logicInput: { type: 'LogicInput' },
fileInput: { type: 'FileInput' },
provoker_input: { type: 'Provoker_input' },
person_input: { type: 'Person_input' },
imageInput: { type: 'ImageInput' }
}
refs: [
{
serverId: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
id: '862c2a0d-c553-4dab-a720-f370802a03c1',
types: [ 'Item', 'Zone', 'BaseObject', 'SpatialObject' ],
global: true,
name: 'Зона 1',
precedence: 50,
is_water_zone: true,
precedence_max: 100,
altitude: -65535,
trace_factor: 1,
alarm_weight: 2,
state: 'ok.normal',
command: 'activate',
precedence_min: 0,
alarm_info: '{"alarm_factor":1,"alarm_precedence":0,"state_before":"alarm.alarm","state_after":"ok.normal","members":{"3d694a91-c6f8-423d-9c8b-17a005caf9b9":{"type":"IpPTZVideoCamera","state":"ok.normal","datetime":1659036334,"weight":1,"precedence":50,"importance":1,"alarm":false,"value":"ok.normal"},"b6c150c5-2402-4cbe-9730-a6fa3fdc2c83":{"type":"BOLID_VolumeSensor","state":"ok.normal","datetime":1659036337,"weight":1,"precedence":50,"importance":1,"alarm":false,"value":"ok.normal"},"af998922-1a8b-40af-afe9-c71b502bc018":{"type":"LowCurrentSirenMeta","weight":0,"precedence":50,"importance":1,"alarm":false},"cbfdb567-ea0f-4d24-b5db-9d135a467736":{"type":"StreetLighting","state":"ok.true","datetime":1659036328,"weight":0,"precedence":50,"importance":0,"alarm":false,"value":"ok.true"},"c2f58334-ebf4-4fff-b990-a7cae44ca463":{"type":"StreetLighting","state":"ok.true","datetime":1659036328,"weight":0,"precedence":50,"importance":0,"alarm":false,"value":"ok.true"}}}',
position: 'POINT(0 0)',
alarm_factor: 1,
ignoreTimeout: 0,
gpsContent: { type: 'GpsProviderIn' },
positionContent: { type: 'PositionContent' },
causeOf: { type: 'CauseOf' },
logicOutput: { type: 'LogicOutput' },
zoneOutputPin: { type: 'ZoneOutputPin' },
linkedItems: [
'3d694a91-c6f8-423d-9c8b-17a005caf9b9',
'862c2a0d-c553-4dab-a720-f370802a03c1',
'b6c150c5-2402-4cbe-9730-a6fa3fdc2c83',
'862c2a0d-c553-4dab-a720-f370802a03c1',
'af998922-1a8b-40af-afe9-c71b502bc018',
'862c2a0d-c553-4dab-a720-f370802a03c1',
'cbfdb567-ea0f-4d24-b5db-9d135a467736',
'862c2a0d-c553-4dab-a720-f370802a03c1',
'c2f58334-ebf4-4fff-b990-a7cae44ca463',
'862c2a0d-c553-4dab-a720-f370802a03c1'
],
logicInput: { type: 'LogicInput' },
fileInput: { type: 'FileInput' },
provoker_input: { type: 'Provoker_input' },
person_input: { type: 'Person_input' },
imageInput: { type: 'ImageInput' }
}
]
создадим новый тестовый объект и выведем результат создания на экран
run(async ({ serverId, changeGraph }) => {
var post1 = blankObject(serverId, 'item');
var updates = [post1.update('type','MilitaryPost'), post1.update('name','Должность') ];
var changes = await changeGraph(updates);
loadChanges(changes);
console.log(changes);
});
Promise { <pending> }
OUTPUT: [1,"integra-s",{"authmethods":["integra-db"],"roles":{"caller":{},"subscriber":{}}}]
INPUT: [4,"integra-db",{}]
OUTPUT: [5,"2b791514-2472-409f-997b-c8018e53b573",{}]
INPUT: [2,140052119719672,{"authrole":"firefly.user","authmethod":"integra-db","authprovider":"integra-s","roles":{"broker":{"features":{"publisher_identification":true,"publisher_exclusion":true,"subscriber_blackwhite_listing":true}},"dealer":{"features":{"prog...
OUTPUT: [48,14,{"disclose_me":true},"com.integra.ember.call_stored",["server.get",[0]],{}]
INPUT: [50,14,{},["{\"5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5\": {\"is_local\": true, \"status\": \"online\", \"position\": \"POINT(0 0)\", \"hash\": \"e2ba6b08-dc48-36d2-814a-af37201bdb38\", \"name\": \"Local server\", \"adm_level\": null, \"router_url\": \"localh...
localServerId: 5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5
OUTPUT: [48,15,{"disclose_me":true},"com.integra.ember.call_stored",["graph.get",["5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5",0]],{}]
INPUT: [50,15,{},["{\"graph_version\": 2498098, \"max_version\": 2498127, \"links\": {\"920e99d9-8449-457f-b2cc-9c2c7b04918b\": {\"params\": {\"out\": {\"version\": 2498098, \"value\": \"d79ec1a3-4ac1-4e37-916b-d59bbe8cfa2a.logicOutput\", \"datetime\": 166255044...
items: 35
links: 28
OUTPUT: [48,16,{"disclose_me":true},"com.integra.ember.put",[[{"operation":"create","entity":"item","server":"5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5","owner":"5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5","id":"55e848ed-64a6-4593-82d6-9db917033b66","params":{"type":{"value":"MilitaryPost"}},"datetime":0},{"operation":"update","entity":"item","server":"5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5","owner":"5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5","id":"55e848ed-64a6-4593-82d6-9db917033b66","params":{"name":{"value":"Должность"}},"datetime":0}]],{}]
INPUT: [50,16,{},[[{"status":null,"paramid":127563,"name":null,"server":"5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5","entity":"item","value":null,"txid":23745929,"version":2498128,"owner":"5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5","operation":"create","datetime":166255067...
[
{
status: null,
paramid: 127563,
name: null,
server: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
entity: 'item',
value: null,
txid: 23745929,
version: 2498128,
owner: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
operation: 'create',
datetime: 1662550672,
type: 'MilitaryPost',
id: '55e848ed-64a6-4593-82d6-9db917033b66'
},
{
status: null,
paramid: 646599,
name: 'categoryName',
server: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
entity: 'item',
value: null,
txid: 23745929,
version: 2498129,
owner: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
operation: 'update',
datetime: 1662550672,
type: 'MilitaryPost',
id: '55e848ed-64a6-4593-82d6-9db917033b66'
},
{
status: null,
paramid: 646600,
name: 'dateOfAppointment',
server: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
entity: 'item',
value: null,
txid: 23745929,
version: 2498130,
owner: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
operation: 'update',
datetime: 1662550672,
type: 'MilitaryPost',
id: '55e848ed-64a6-4593-82d6-9db917033b66'
},
{
status: null,
paramid: 646601,
name: 'groupName',
server: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
entity: 'item',
value: null,
txid: 23745929,
version: 2498131,
owner: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
operation: 'update',
datetime: 1662550672,
type: 'MilitaryPost',
id: '55e848ed-64a6-4593-82d6-9db917033b66'
},
{
status: null,
paramid: 646602,
name: 'militaryUnit',
server: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
entity: 'item',
value: null,
txid: 23745929,
version: 2498132,
owner: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
operation: 'update',
datetime: 1662550672,
type: 'MilitaryPost',
id: '55e848ed-64a6-4593-82d6-9db917033b66'
},
{
status: null,
paramid: 646603,
name: 'name',
server: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
entity: 'item',
value: null,
txid: 23745929,
version: 2498133,
owner: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
operation: 'update',
datetime: 1662550672,
type: 'MilitaryPost',
id: '55e848ed-64a6-4593-82d6-9db917033b66'
},
{
status: null,
paramid: 646604,
name: 'personalNumber',
server: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
entity: 'item',
value: null,
txid: 23745929,
version: 2498134,
owner: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
operation: 'update',
datetime: 1662550672,
type: 'MilitaryPost',
id: '55e848ed-64a6-4593-82d6-9db917033b66'
},
{
status: null,
paramid: 646605,
name: 'staffId',
server: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
entity: 'item',
value: null,
txid: 23745929,
version: 2498135,
owner: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
operation: 'update',
datetime: 1662550672,
type: 'MilitaryPost',
id: '55e848ed-64a6-4593-82d6-9db917033b66'
},
{
status: null,
paramid: 646606,
name: 'state',
server: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
entity: 'item',
value: null,
txid: 23745929,
version: 2498136,
owner: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
operation: 'update',
datetime: 1662550672,
type: 'MilitaryPost',
id: '55e848ed-64a6-4593-82d6-9db917033b66'
},
{
status: null,
paramid: 127564,
name: null,
server: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
entity: 'pin',
value: null,
txid: 23745929,
version: 2498137,
owner: '55e848ed-64a6-4593-82d6-9db917033b66',
operation: 'create',
datetime: 1662550672,
type: 'MilitaryContainer',
id: 'militaryContainer'
},
{
status: null,
paramid: 127565,
name: null,
server: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
entity: 'pin',
value: null,
txid: 23745929,
version: 2498138,
owner: '55e848ed-64a6-4593-82d6-9db917033b66',
operation: 'create',
datetime: 1662550672,
type: 'MilitaryContent',
id: 'militaryContent'
},
{
status: null,
paramid: 127566,
name: null,
server: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
entity: 'pin',
value: null,
txid: 23745929,
version: 2498139,
owner: '55e848ed-64a6-4593-82d6-9db917033b66',
operation: 'create',
datetime: 1662550672,
type: 'MilitaryTempContainer',
id: 'militaryTempContainer'
},
{
status: null,
paramid: 127567,
name: null,
server: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
entity: 'pin',
value: null,
txid: 23745929,
version: 2498140,
owner: '55e848ed-64a6-4593-82d6-9db917033b66',
operation: 'create',
datetime: 1662550672,
type: 'MilitaryTempContent',
id: 'militaryTempContent'
},
{
status: null,
paramid: 127568,
name: null,
server: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
entity: 'pin',
value: null,
txid: 23745929,
version: 2498141,
owner: '55e848ed-64a6-4593-82d6-9db917033b66',
operation: 'create',
datetime: 1662550672,
type: 'LogicInput',
id: 'logicInput'
},
{
status: null,
paramid: 127569,
name: null,
server: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
entity: 'pin',
value: null,
txid: 23745929,
version: 2498142,
owner: '55e848ed-64a6-4593-82d6-9db917033b66',
operation: 'create',
datetime: 1662550672,
type: 'LogicOutput',
id: 'logicOutput'
},
{
status: null,
paramid: 646603,
name: 'name',
server: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
entity: 'item',
value: 'Должность',
txid: 23745929,
version: 2498143,
owner: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
operation: 'update',
datetime: 1662550672,
type: 'MilitaryPost',
id: '55e848ed-64a6-4593-82d6-9db917033b66'
}
]
OUTPUT: [6,{},"wamp.close.goodbye_and_out"]
INPUT: [6,{},"wamp.goodbye.normal"]
(node:14058) UnhandledPromiseRejectionWarning: GOODBYE (node:14058) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 6)
теперь найдем этот объект в графе
var post1 = queryPath('MilitaryPost/1')
post1
{
pins: {
militaryContent: {
types: [Array],
name: 'militaryContent',
id: '3d02e7cb-ce66-4c6f-ab2e-d7f782538352.militaryContent',
params: {},
search: [Function: queryPath],
update: [Function (anonymous)],
delete: [Function (anonymous)],
get: [Function (anonymous)],
refs: [Function (anonymous)],
ref: [Function (anonymous)],
parse: [Function (anonymous)],
eval: [Function (anonymous)],
time: 1662550669.962
},
militaryTempContent: {
types: [Array],
name: 'militaryTempContent',
id: '3d02e7cb-ce66-4c6f-ab2e-d7f782538352.militaryTempContent',
params: {},
search: [Function: queryPath],
update: [Function (anonymous)],
delete: [Function (anonymous)],
get: [Function (anonymous)],
refs: [Function (anonymous)],
ref: [Function (anonymous)],
parse: [Function (anonymous)],
eval: [Function (anonymous)],
time: 1662550669.962
},
militaryContainer: {
types: [Array],
name: 'militaryContainer',
id: '3d02e7cb-ce66-4c6f-ab2e-d7f782538352.militaryContainer',
params: {},
search: [Function: queryPath],
update: [Function (anonymous)],
delete: [Function (anonymous)],
get: [Function (anonymous)],
refs: [Function (anonymous)],
ref: [Function (anonymous)],
parse: [Function (anonymous)],
eval: [Function (anonymous)],
time: 1662550669.962
},
logicOutput: {
types: [Array],
name: 'logicOutput',
id: '3d02e7cb-ce66-4c6f-ab2e-d7f782538352.logicOutput',
params: {},
search: [Function: queryPath],
update: [Function (anonymous)],
delete: [Function (anonymous)],
get: [Function (anonymous)],
refs: [Function (anonymous)],
ref: [Function (anonymous)],
parse: [Function (anonymous)],
eval: [Function (anonymous)],
time: 1662550669.962
},
logicInput: {
types: [Array],
name: 'logicInput',
id: '3d02e7cb-ce66-4c6f-ab2e-d7f782538352.logicInput',
params: {},
search: [Function: queryPath],
update: [Function (anonymous)],
delete: [Function (anonymous)],
get: [Function (anonymous)],
refs: [Function (anonymous)],
ref: [Function (anonymous)],
parse: [Function (anonymous)],
eval: [Function (anonymous)],
time: 1662550669.962
},
militaryTempContainer: {
types: [Array],
name: 'militaryTempContainer',
id: '3d02e7cb-ce66-4c6f-ab2e-d7f782538352.militaryTempContainer',
params: {},
search: [Function: queryPath],
update: [Function (anonymous)],
delete: [Function (anonymous)],
get: [Function (anonymous)],
refs: [Function (anonymous)],
ref: [Function (anonymous)],
parse: [Function (anonymous)],
eval: [Function (anonymous)],
time: 1662550669.962
}
},
params: {
state: { version: 2498070, value: null, datetime: 1662550419 },
name: { version: 2498077, value: 'Должность', datetime: 1662550419 }
},
types: [ 'Item', 'MilitaryPost', 'Category', 'MilitaryCategory' ],
serverId: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
id: '3d02e7cb-ce66-4c6f-ab2e-d7f782538352',
name: 'Должность',
position: [],
search: [Function: queryPath],
update: [Function (anonymous)],
delete: [Function (anonymous)],
get: [Function (anonymous)],
refs: [Function (anonymous)],
ref: [Function (anonymous)],
parse: [Function (anonymous)],
eval: [Function (anonymous)],
time: 1662550669.962
}
создадим тестовую метрику и выведем результат создания на экран
run(async ({ serverId, changeGraph }) => {
var metric1 = blankObject(serverId, 'item')
var updates = [metric1.update('type','Metric'), metric1.update('name','Metric1') ]
var changes = await changeGraph(updates);
loadChanges(changes);
console.log(changes);
});
Promise { <pending> }
OUTPUT: [1,"integra-s",{"authmethods":["integra-db"],"roles":{"caller":{},"subscriber":{}}}]
INPUT: [4,"integra-db",{}]
OUTPUT: [5,"ef9a1d05-fd45-4221-b812-38d0baf4634f",{}]
INPUT: [2,6181946753485369,{"authrole":"firefly.user","authmethod":"integra-db","authprovider":"integra-s","roles":{"broker":{"features":{"publisher_identification":true,"publisher_exclusion":true,"subscriber_blackwhite_listing":true}},"dealer":{"features":{"pro...
OUTPUT: [48,17,{"disclose_me":true},"com.integra.ember.call_stored",["server.get",[0]],{}]
INPUT: [50,17,{},["{\"5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5\": {\"is_local\": true, \"status\": \"online\", \"position\": \"POINT(0 0)\", \"hash\": \"e2ba6b08-dc48-36d2-814a-af37201bdb38\", \"name\": \"Local server\", \"adm_level\": null, \"router_url\": \"localh...
localServerId: 5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5
OUTPUT: [48,18,{"disclose_me":true},"com.integra.ember.call_stored",["graph.get",["5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5",0]],{}]
INPUT: [50,18,{},["{\"graph_version\": 2498143, \"max_version\": 2498143, \"links\": {\"920e99d9-8449-457f-b2cc-9c2c7b04918b\": {\"params\": {\"out\": {\"version\": 2498098, \"value\": \"d79ec1a3-4ac1-4e37-916b-d59bbe8cfa2a.logicOutput\", \"datetime\": 166255044...
items: 36
links: 28
OUTPUT: [48,19,{"disclose_me":true},"com.integra.ember.put",[[{"operation":"create","entity":"item","server":"5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5","owner":"5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5","id":"a08399ef-ca80-4321-8036-ee186622d786","params":{"type":{"value":"Metric"}},"datetime":0},{"operation":"update","entity":"item","server":"5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5","owner":"5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5","id":"a08399ef-ca80-4321-8036-ee186622d786","params":{"name":{"value":"Metric1"}},"datetime":0}]],{}]
INPUT: [50,19,{},[[{"status":null,"paramid":127570,"name":null,"server":"5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5","entity":"item","value":null,"txid":23745931,"version":2498144,"owner":"5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5","operation":"create","datetime":166255068...
[
{
status: null,
paramid: 127570,
name: null,
server: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
entity: 'item',
value: null,
txid: 23745931,
version: 2498144,
owner: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
operation: 'create',
datetime: 1662550683,
type: 'Metric',
id: 'a08399ef-ca80-4321-8036-ee186622d786'
},
{
status: null,
paramid: 646607,
name: 'args',
server: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
entity: 'item',
value: null,
txid: 23745931,
version: 2498145,
owner: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
operation: 'update',
datetime: 1662550683,
type: 'Metric',
id: 'a08399ef-ca80-4321-8036-ee186622d786'
},
{
status: null,
paramid: 646608,
name: 'binding',
server: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
entity: 'item',
value: null,
txid: 23745931,
version: 2498146,
owner: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
operation: 'update',
datetime: 1662550683,
type: 'Metric',
id: 'a08399ef-ca80-4321-8036-ee186622d786'
},
{
status: null,
paramid: 646609,
name: 'description',
server: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
entity: 'item',
value: null,
txid: 23745931,
version: 2498147,
owner: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
operation: 'update',
datetime: 1662550683,
type: 'Metric',
id: 'a08399ef-ca80-4321-8036-ee186622d786'
},
{
status: null,
paramid: 646610,
name: 'error',
server: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
entity: 'item',
value: null,
txid: 23745931,
version: 2498148,
owner: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
operation: 'update',
datetime: 1662550683,
type: 'Metric',
id: 'a08399ef-ca80-4321-8036-ee186622d786'
},
{
status: null,
paramid: 646611,
name: 'kwargs',
server: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
entity: 'item',
value: null,
txid: 23745931,
version: 2498149,
owner: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
operation: 'update',
datetime: 1662550683,
type: 'Metric',
id: 'a08399ef-ca80-4321-8036-ee186622d786'
},
{
status: null,
paramid: 646612,
name: 'name',
server: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
entity: 'item',
value: null,
txid: 23745931,
version: 2498150,
owner: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
operation: 'update',
datetime: 1662550683,
type: 'Metric',
id: 'a08399ef-ca80-4321-8036-ee186622d786'
},
{
status: null,
paramid: 646613,
name: 'owner',
server: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
entity: 'item',
value: null,
txid: 23745931,
version: 2498151,
owner: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
operation: 'update',
datetime: 1662550683,
type: 'Metric',
id: 'a08399ef-ca80-4321-8036-ee186622d786'
},
{
status: null,
paramid: 646614,
name: 'state',
server: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
entity: 'item',
value: null,
txid: 23745931,
version: 2498152,
owner: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
operation: 'update',
datetime: 1662550683,
type: 'Metric',
id: 'a08399ef-ca80-4321-8036-ee186622d786'
},
{
status: null,
paramid: 646615,
name: 'value',
server: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
entity: 'item',
value: null,
txid: 23745931,
version: 2498153,
owner: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
operation: 'update',
datetime: 1662550683,
type: 'Metric',
id: 'a08399ef-ca80-4321-8036-ee186622d786'
},
{
status: null,
paramid: 646616,
name: 'weight',
server: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
entity: 'item',
value: null,
txid: 23745931,
version: 2498154,
owner: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
operation: 'update',
datetime: 1662550683,
type: 'Metric',
id: 'a08399ef-ca80-4321-8036-ee186622d786'
},
{
status: null,
paramid: 127571,
name: null,
server: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
entity: 'pin',
value: null,
txid: 23745931,
version: 2498155,
owner: 'a08399ef-ca80-4321-8036-ee186622d786',
operation: 'create',
datetime: 1662550683,
type: 'SoftwareContent',
id: 'softwareContent'
},
{
status: null,
paramid: 127572,
name: null,
server: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
entity: 'pin',
value: null,
txid: 23745931,
version: 2498156,
owner: 'a08399ef-ca80-4321-8036-ee186622d786',
operation: 'create',
datetime: 1662550683,
type: 'LogicOutput',
id: 'logicOutput'
},
{
status: null,
paramid: 127573,
name: null,
server: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
entity: 'pin',
value: null,
txid: 23745931,
version: 2498157,
owner: 'a08399ef-ca80-4321-8036-ee186622d786',
operation: 'create',
datetime: 1662550683,
type: 'LogicInput',
id: 'logicInput'
},
{
status: null,
paramid: 646612,
name: 'name',
server: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
entity: 'item',
value: 'Metric1',
txid: 23745931,
version: 2498158,
owner: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
operation: 'update',
datetime: 1662550683,
type: 'Metric',
id: 'a08399ef-ca80-4321-8036-ee186622d786'
}
]
OUTPUT: [6,{},"wamp.close.goodbye_and_out"]
INPUT: [6,{},"wamp.goodbye.normal"]
(node:14058) UnhandledPromiseRejectionWarning: GOODBYE (node:14058) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 7)
теперь найдем эту метрику в графе
var metric1 = queryPath('Metric1/1')
metric1
{
pins: {
softwareContent: {
types: [Array],
name: 'softwareContent',
id: 'ab4a7e0b-ddf2-417a-b5e5-98deb30d36ae.softwareContent',
params: {},
search: [Function: queryPath],
update: [Function (anonymous)],
delete: [Function (anonymous)],
get: [Function (anonymous)],
refs: [Function (anonymous)],
ref: [Function (anonymous)],
parse: [Function (anonymous)],
eval: [Function (anonymous)],
time: 1662550680.475
},
logicInput: {
types: [Array],
name: 'logicInput',
id: 'ab4a7e0b-ddf2-417a-b5e5-98deb30d36ae.logicInput',
params: {},
search: [Function: queryPath],
update: [Function (anonymous)],
delete: [Function (anonymous)],
get: [Function (anonymous)],
refs: [Function (anonymous)],
ref: [Function (anonymous)],
parse: [Function (anonymous)],
eval: [Function (anonymous)],
time: 1662550680.475
},
logicOutput: {
types: [Array],
name: 'logicOutput',
id: 'ab4a7e0b-ddf2-417a-b5e5-98deb30d36ae.logicOutput',
params: {},
search: [Function: queryPath],
update: [Function (anonymous)],
delete: [Function (anonymous)],
get: [Function (anonymous)],
refs: [Function (anonymous)],
ref: [Function (anonymous)],
parse: [Function (anonymous)],
eval: [Function (anonymous)],
time: 1662550680.475
}
},
params: {
state: { version: 2498086, value: null, datetime: 1662550432 },
name: { version: 2498092, value: 'Metric1', datetime: 1662550432 }
},
types: [ 'Item', 'Metric', 'Software' ],
serverId: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
id: 'ab4a7e0b-ddf2-417a-b5e5-98deb30d36ae',
name: 'Metric1',
position: [],
search: [Function: queryPath],
update: [Function (anonymous)],
delete: [Function (anonymous)],
get: [Function (anonymous)],
refs: [Function (anonymous)],
ref: [Function (anonymous)],
parse: [Function (anonymous)],
eval: [Function (anonymous)],
time: 1662550680.475
}
создадим линк соединяющий тестовый датчик и метрику и выведем результат создания на экран
run(async ({ serverId, changeGraph }) => {
var link1 = blankObject(serverId, 'link');
var updates = [
link1.update('type','LogicLink'),
link1.update('in',post1.pins.logicInput.id),
link1.update('out',metric1.pins.logicOutput.id),
];
console.log(updates);
var changes = await changeGraph(updates);
loadChanges(changes);
console.log(changes);
});
Promise { <pending> }
OUTPUT: [1,"integra-s",{"authmethods":["integra-db"],"roles":{"caller":{},"subscriber":{}}}]
INPUT: [4,"integra-db",{}]
OUTPUT: [5,"df6f5d67-51ac-4208-bcd4-dda8f154399c",{}]
INPUT: [2,4812682233207926,{"authrole":"firefly.user","authmethod":"integra-db","authprovider":"integra-s","roles":{"broker":{"features":{"publisher_identification":true,"publisher_exclusion":true,"subscriber_blackwhite_listing":true}},"dealer":{"features":{"pro...
OUTPUT: [48,20,{"disclose_me":true},"com.integra.ember.call_stored",["server.get",[0]],{}]
INPUT: [50,20,{},["{\"5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5\": {\"is_local\": true, \"status\": \"online\", \"position\": \"POINT(0 0)\", \"hash\": \"e2ba6b08-dc48-36d2-814a-af37201bdb38\", \"name\": \"Local server\", \"adm_level\": null, \"router_url\": \"localh...
localServerId: 5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5
OUTPUT: [48,21,{"disclose_me":true},"com.integra.ember.call_stored",["graph.get",["5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5",0]],{}]
INPUT: [50,21,{},["{\"graph_version\": 2498158, \"max_version\": 2498158, \"links\": {\"920e99d9-8449-457f-b2cc-9c2c7b04918b\": {\"params\": {\"out\": {\"version\": 2498098, \"value\": \"d79ec1a3-4ac1-4e37-916b-d59bbe8cfa2a.logicOutput\", \"datetime\": 166255044...
items: 37
links: 28
[
{
operation: 'create',
entity: 'link',
server: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
owner: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
id: '1b021cdc-32f4-47bf-b8d0-c1f5334fdf63',
params: { type: [Object] },
datetime: 0
},
{
operation: 'update',
entity: 'link',
server: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
owner: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
id: '1b021cdc-32f4-47bf-b8d0-c1f5334fdf63',
params: { in: [Object] },
datetime: 0
},
{
operation: 'update',
entity: 'link',
server: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
owner: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
id: '1b021cdc-32f4-47bf-b8d0-c1f5334fdf63',
params: { out: [Object] },
datetime: 0
}
]
OUTPUT: [48,22,{"disclose_me":true},"com.integra.ember.put",[[{"operation":"create","entity":"link","server":"5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5","owner":"5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5","id":"1b021cdc-32f4-47bf-b8d0-c1f5334fdf63","params":{"type":{"value":"LogicLink"}},"datetime":0},{"operation":"update","entity":"link","server":"5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5","owner":"5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5","id":"1b021cdc-32f4-47bf-b8d0-c1f5334fdf63","params":{"in":{"value":"3d02e7cb-ce66-4c6f-ab2e-d7f782538352.logicInput"}},"datetime":0},{"operation":"update","entity":"link","server":"5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5","owner":"5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5","id":"1b021cdc-32f4-47bf-b8d0-c1f5334fdf63","params":{"out":{"value":"ab4a7e0b-ddf2-417a-b5e5-98deb30d36ae.logicOutput"}},"datetime":0}]],{}]
INPUT: [50,22,{},[[{"status":null,"paramid":127574,"name":null,"server":"5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5","entity":"link","value":null,"txid":23745932,"version":2498159,"owner":"5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5","operation":"create","datetime":166255069...
[
{
status: null,
paramid: 127574,
name: null,
server: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
entity: 'link',
value: null,
txid: 23745932,
version: 2498159,
owner: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
operation: 'create',
datetime: 1662550691,
type: 'LogicLink',
id: '1b021cdc-32f4-47bf-b8d0-c1f5334fdf63'
},
{
status: null,
paramid: 646617,
name: 'color',
server: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
entity: 'link',
value: null,
txid: 23745932,
version: 2498160,
owner: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
operation: 'update',
datetime: 1662550691,
type: 'LogicLink',
id: '1b021cdc-32f4-47bf-b8d0-c1f5334fdf63'
},
{
status: null,
paramid: 646618,
name: 'in',
server: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
entity: 'link',
value: null,
txid: 23745932,
version: 2498161,
owner: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
operation: 'update',
datetime: 1662550691,
type: 'LogicLink',
id: '1b021cdc-32f4-47bf-b8d0-c1f5334fdf63'
},
{
status: null,
paramid: 646619,
name: 'out',
server: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
entity: 'link',
value: null,
txid: 23745932,
version: 2498162,
owner: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
operation: 'update',
datetime: 1662550691,
type: 'LogicLink',
id: '1b021cdc-32f4-47bf-b8d0-c1f5334fdf63'
},
{
status: null,
paramid: 646618,
name: 'in',
server: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
entity: 'link',
value: '3d02e7cb-ce66-4c6f-ab2e-d7f782538352.logicInput',
txid: 23745932,
version: 2498163,
owner: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
operation: 'update',
datetime: 1662550691,
type: 'LogicLink',
id: '1b021cdc-32f4-47bf-b8d0-c1f5334fdf63'
},
{
status: null,
paramid: 646619,
name: 'out',
server: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
entity: 'link',
value: 'ab4a7e0b-ddf2-417a-b5e5-98deb30d36ae.logicOutput',
txid: 23745932,
version: 2498164,
owner: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
operation: 'update',
datetime: 1662550691,
type: 'LogicLink',
id: '1b021cdc-32f4-47bf-b8d0-c1f5334fdf63'
}
]
OUTPUT: [6,{},"wamp.close.goodbye_and_out"]
INPUT: [6,{},"wamp.goodbye.normal"]
(node:14058) UnhandledPromiseRejectionWarning: GOODBYE (node:14058) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 8)
можно протестировать то, что получилось, попробовав найти один датчик через связь с другим
metric1.search('LogicLink/MilitaryPost')
[
{
pins: {
militaryContent: [Object],
militaryTempContent: [Object],
militaryContainer: [Object],
logicOutput: [Object],
logicInput: [Object],
militaryTempContainer: [Object]
},
params: { state: [Object], name: [Object] },
types: [ 'Item', 'MilitaryPost', 'Category', 'MilitaryCategory' ],
serverId: '5331e7ee-08aa-4655-90aa-fc1bd2ab3ba5',
id: '3d02e7cb-ce66-4c6f-ab2e-d7f782538352',
name: 'Должность',
position: [],
search: [Function: queryPath],
update: [Function (anonymous)],
delete: [Function (anonymous)],
get: [Function (anonymous)],
refs: [Function (anonymous)],
ref: [Function (anonymous)],
parse: [Function (anonymous)],
eval: [Function (anonymous)],
time: 1662550687.988
}
]
system(`jupyter-nbconvert --output-dir=./static --to HTML docs-supergraph.ipynb`)
[NbConvertApp] Converting notebook docs-supergraph.ipynb to HTML [NbConvertApp] Writing 885385 bytes to static/docs-supergraph.html