@node-i3x/demo-embedded 0.1.0 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -82,6 +82,13 @@ See the [Embedding Tutorial](../pseudo-session-connector/TUTORIAL.md) for a step
82
82
 
83
83
  ## License
84
84
 
85
- **AGPL-3.0-or-later** -- Free for open-source projects.
85
+ Dual-licensed:
86
86
 
87
- For commercial / proprietary use, contact [Sterfive](https://sterfive.com) for a commercial license.
87
+ - **AGPL-3.0-or-later** -- you may use, modify, and distribute this software
88
+ freely, provided that all derivative works and network-accessible deployments
89
+ also make their complete source code available under the AGPL.
90
+ - **Sterfive Commercial License** -- allows proprietary and closed-source use
91
+ without copyleft obligations.
92
+
93
+ See [LICENSING.md](../../LICENSING.md) for details, or contact
94
+ [Sterfive](https://sterfive.com) for commercial licensing.
package/dist/client.js CHANGED
@@ -4,7 +4,7 @@ import{parseArgs as q}from"util";var{values:j}=q({options:{url:{type:"string",de
4
4
 
5
5
  `),P=(await h("/v1/info")).result.serverName;let t=await h("/v1/objects?root=true"),s=["Locations","Server","Aliases"],r=t.result.filter(o=>!s.includes(o.displayName));process.stdout.write(` Found ${r.length} user-defined root(s)
6
6
  `);let i=[];for(let o of r)await T(o,i);for(let o of l)process.stdout.write(` \u{1F4E6} ${o.name} (${o.properties.length} props)
7
- `);return i}async function T(e,t){if(C.set(e.elementId,e.displayName),!e.isComposition)return;t.push(e.id);let s=await p("/v1/objects/related",{elementIds:[e.elementId]});if(!s.results[0]?.success)return;let r=s.results[0]?.result.filter(a=>a.sourceRelationship==="HasComponent"),i=r.filter(a=>a.object.isComposition),o=r.filter(a=>!a.object.isComposition);if(o.length>0){let a=D(e.displayName),d={id:e.elementId,name:e.displayName,icon:a,properties:o.map(u=>(C.set(u.object.elementId,u.object.displayName),{id:u.object.elementId,name:u.object.displayName,value:"\u2014",quality:"Unknown",timestamp:"",changed:!1}))};l.push(d)}for(let a of i)await T(a.object,t)}function D(e){let t=e.toLowerCase();return t.includes("pump")?"\u{1F4A7}":t.includes("heater")?"\u{1F525}":t.includes("conveyor")?"\u{1F3ED}":t.includes("factory")?"\u{1F3D7}\uFE0F":"\u{1F4E6}"}async function F(){let e=l.map(s=>s.id);if(e.length===0)return;let t=await p("/v1/objects/value",{elementIds:e,maxDepth:3});for(let s of t.results){if(!s.success||!s.result.isComposition||!s.result.components)continue;let r=l.find(i=>i.id===s.elementId);if(r)for(let i of r.properties){let o=s.result.components[i.id];o&&(i.value=o.value,i.quality=o.quality,i.timestamp=o.timestamp)}}}async function V(){let e=l.map(s=>s.id);if(e.length===0)return;m=(await p("/v1/subscriptions",{clientId:"dashboard-client",displayName:"Dashboard Monitor"})).result.subscriptionId,await p("/v1/subscriptions/register",{subscriptionId:m,elementIds:e,maxDepth:3})}async function M(){try{let t=(await p("/v1/subscriptions/sync",{subscriptionId:m,acknowledgeSequence:f})).result;if(!t||t.length===0)return;N+=t.length,S++;for(let s of l)for(let r of s.properties)r.changed=!1;for(let s of t){if(s.sequenceNumber>f&&(f=s.sequenceNumber),!s.value?.isComposition||!s.value?.components)continue;let r=l.find(i=>i.id===s.elementId);if(r)for(let[i,o]of Object.entries(s.value.components)){let a=r.properties.find(d=>d.id===i);a&&(a.value=o.value,a.quality=o.quality,a.timestamp=o.timestamp,a.changed=!0)}}g=""}catch(e){g=String(e)}}function v(){let e=[],t=n.reset,s=new Date().toLocaleTimeString();e.push(""),e.push(` ${n.bgHeader}${n.white}${n.bold} \u{1F4E1} i3X Dashboard \u2014 ${P} ${t} ${n.dim}${s}${t}`),e.push("");let r=[];r.push(`${n.green}\u25CF Connected${t}`),r.push(`${n.dim}Updates: ${S}${t}`),r.push(`${n.dim}Changes: ${N}${t}`),r.push(`${n.dim}Seq: ${f}${t}`),e.push(` ${r.join(" \u2502 ")}`),e.push("");for(let i=0;i<l.length;i+=2){let o=x(l[i]),a=i+1<l.length?x(l[i+1]):null,d=Math.max(o.length,a?.length??0);for(let u=0;u<d;u++){let y=o[u]??" ".repeat(w),$=a?a[u]??" ".repeat(w):"";e.push(` ${y} ${$}`)}e.push("")}g&&e.push(` ${n.red}\u26A0 ${g}${t}`),e.push(` ${n.dim}Press Ctrl+C to stop${t}`),e.push(""),process.stdout.write(n.home+e.join(`
7
+ `);return i}async function T(e,t){if(C.set(e.elementId,e.displayName),!e.isComposition)return;t.push(e.elementId);let s=await p("/v1/objects/related",{elementIds:[e.elementId]});if(!s.results[0]?.success)return;let r=s.results[0]?.result.filter(a=>a.sourceRelationship==="HasComponent"),i=r.filter(a=>a.object.isComposition),o=r.filter(a=>!a.object.isComposition);if(o.length>0){let a=D(e.displayName),d={id:e.elementId,name:e.displayName,icon:a,properties:o.map(u=>(C.set(u.object.elementId,u.object.displayName),{id:u.object.elementId,name:u.object.displayName,value:"\u2014",quality:"Unknown",timestamp:"",changed:!1}))};l.push(d)}for(let a of i)await T(a.object,t)}function D(e){let t=e.toLowerCase();return t.includes("pump")?"\u{1F4A7}":t.includes("heater")?"\u{1F525}":t.includes("conveyor")?"\u{1F3ED}":t.includes("factory")?"\u{1F3D7}\uFE0F":"\u{1F4E6}"}async function F(){let e=l.map(s=>s.id);if(e.length===0)return;let t=await p("/v1/objects/value",{elementIds:e,maxDepth:3});for(let s of t.results){if(!s.success||!s.result.isComposition||!s.result.components)continue;let r=l.find(i=>i.id===s.elementId);if(r)for(let i of r.properties){let o=s.result.components[i.id];o&&(i.value=o.value,i.quality=o.quality,i.timestamp=o.timestamp)}}}async function V(){let e=l.map(s=>s.id);if(e.length===0)return;m=(await p("/v1/subscriptions",{clientId:"dashboard-client",displayName:"Dashboard Monitor"})).result.subscriptionId,await p("/v1/subscriptions/register",{subscriptionId:m,elementIds:e,maxDepth:3})}async function M(){try{let t=(await p("/v1/subscriptions/sync",{subscriptionId:m,acknowledgeSequence:f})).result;if(!t||t.length===0)return;N+=t.length,S++;for(let s of l)for(let r of s.properties)r.changed=!1;for(let s of t){if(s.sequenceNumber>f&&(f=s.sequenceNumber),!s.value?.isComposition||!s.value?.components)continue;let r=l.find(i=>i.id===s.elementId);if(r)for(let[i,o]of Object.entries(s.value.components)){let a=r.properties.find(d=>d.id===i);a&&(a.value=o.value,a.quality=o.quality,a.timestamp=o.timestamp,a.changed=!0)}}g=""}catch(e){g=String(e)}}function v(){let e=[],t=n.reset,s=new Date().toLocaleTimeString();e.push(""),e.push(` ${n.bgHeader}${n.white}${n.bold} \u{1F4E1} i3X Dashboard \u2014 ${P} ${t} ${n.dim}${s}${t}`),e.push("");let r=[];r.push(`${n.green}\u25CF Connected${t}`),r.push(`${n.dim}Updates: ${S}${t}`),r.push(`${n.dim}Changes: ${N}${t}`),r.push(`${n.dim}Seq: ${f}${t}`),e.push(` ${r.join(" \u2502 ")}`),e.push("");for(let i=0;i<l.length;i+=2){let o=x(l[i]),a=i+1<l.length?x(l[i+1]):null,d=Math.max(o.length,a?.length??0);for(let u=0;u<d;u++){let y=o[u]??" ".repeat(w),$=a?a[u]??" ".repeat(w):"";e.push(` ${y} ${$}`)}e.push("")}g&&e.push(` ${n.red}\u26A0 ${g}${t}`),e.push(` ${n.dim}Press Ctrl+C to stop${t}`),e.push(""),process.stdout.write(n.home+e.join(`
8
8
  `))}function x(e){let t=[],s=n.reset,r=w;t.push(`${n.dim}${k(r)}${s}`);let i=`${e.icon} ${n.bold}${n.cyan}${e.name}${s}`;t.push(`${n.dim}${I(i,r)}${s}`),t.push(`${n.dim}${L(r)}${s}`);for(let o of e.properties){let a=U(o.name),{text:d,color:u}=B(o.value,o.name),$=`${o.changed?n.yellow:n.dim}${a.padEnd(18)}${s} ${u}${d}${s}`;t.push(`${n.dim}${I($,r)}${s}`)}return t.push(`${n.dim}${O(r)}${s}`),t}function U(e){return e.replace(" (\xB0C)"," \xB0C").replace(" (bar)"," bar").replace(" (L/min)"," L/min").replace(" (m/s)"," m/s").replace(" (%)"," %")}function B(e,t){if(typeof e=="boolean")return t.toLowerCase().includes("heater")?e?{text:"\u{1F525} ON",color:n.red}:{text:" OFF",color:n.gray}:e?{text:"\u25CF ON",color:n.green}:{text:"\u25CB OFF",color:n.gray};if(typeof e=="number"){let s=t.toLowerCase(),r=n.white;return s.includes("temperature")||s.includes("temp")?e>180?r=n.red:e>100?r=n.yellow:r=n.green:s.includes("pressure")?e>5.5?r=n.red:e>4.5?r=n.yellow:r=n.green:s.includes("power")&&(e>80?r=n.red:e>0?r=n.yellow:r=n.gray),{text:Number.isInteger(e)?e.toLocaleString():e.toFixed(2),color:r}}return{text:String(e??"\u2014"),color:n.white}}async function H(){try{await h("/health")}catch{console.error(`
9
9
  \u274C Cannot reach i3X server at ${b}`),console.error(` Start the demo first:
10
10
  npm run demo -w packages/demo-embedded
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/client.ts"],"mappings":"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","names":["parseArgs","clientArgs","BASE_URL","BASE","ESC","ansi","get","path","res","post","body","nameById","cards","subId","lastSeq","updateCount","totalChanges","serverName","lastError","CARD_W","boxTop","w","boxMid","boxBot","boxRow","content","visible","pad","discover","roots","skipNames","userRoots","r","compositeIds","root","walkTree","card","obj","related","children","childAssets","c","childProps","icon","iconForAsset","child","name","n","readInitialValues","ids","values","entry","prop","vqt","createSubscription","syncUpdates","updates","u","propId","p","err","render","lines","now","statusParts","left","renderCard","right","maxLines","row","l","rr","title","label","cleanLabel","valText","color","formatPropValue","line","v","main","_compositeIds","sleep","cleanup","iteration","ms"]}
1
+ {"version":3,"sources":["../src/client.ts"],"mappings":"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","names":["parseArgs","clientArgs","BASE_URL","BASE","ESC","ansi","get","path","res","post","body","nameById","cards","subId","lastSeq","updateCount","totalChanges","serverName","lastError","CARD_W","boxTop","w","boxMid","boxBot","boxRow","content","visible","pad","discover","roots","skipNames","userRoots","r","compositeIds","root","walkTree","card","obj","related","children","childAssets","c","childProps","icon","iconForAsset","child","name","n","readInitialValues","ids","values","entry","prop","vqt","createSubscription","syncUpdates","updates","u","propId","p","err","render","lines","now","statusParts","left","renderCard","right","maxLines","row","l","rr","title","label","cleanLabel","valText","color","formatPropValue","line","v","main","_compositeIds","sleep","cleanup","iteration","ms"]}
package/dist/index.js CHANGED
@@ -1,16 +1,16 @@
1
1
  #!/usr/bin/env node
2
- import{consoleLogger as I,HistoryService as A,ModelService as U,SubscriptionService as R,ValueService as $}from"@node-i3x/core";import{PseudoSessionDataSourceAdapter as x}from"@node-i3x/pseudo-session-connector";import{createApp as E}from"@node-i3x/rest-server";import{DataType as e,nodesets as F,OPCUAServer as B,Variant as n}from"node-opcua";import{parseArgs as j}from"util";var{values:f}=j({options:{"rest-port":{type:"string",default:"8080"},"opcua-port":{type:"string",default:"48410"},help:{type:"boolean",short:"h",default:!1}}});f.help&&(console.log(`
2
+ import{parseArgs as I}from"util";import{consoleLogger as A,HistoryService as U,ModelService as R,SubscriptionService as $,ValueService as x}from"@node-i3x/core";import{PseudoSessionDataSourceAdapter as E}from"@node-i3x/pseudo-session-connector";import{createApp as F}from"@node-i3x/rest-server";import{DataType as e,nodesets as B,OPCUAServer as j,Variant as n}from"node-opcua";var{values:f}=I({options:{"rest-port":{type:"string",default:"8080"},"opcua-port":{type:"string",default:"48410"},help:{type:"boolean",short:"h",default:!1}}});f.help&&(console.log(`
3
3
  Usage: i3x-demo [options]
4
4
 
5
5
  Options:
6
6
  --rest-port <port> REST API port (default: 8080)
7
7
  --opcua-port <port> OPC UA server port (default: 48410)
8
8
  -h, --help Show this help
9
- `),process.exit(0));var c=parseInt(f["rest-port"],10),T=parseInt(f["opcua-port"],10);function s(a,l,o){a.setValueFromSource(new n({dataType:l,value:o}))}async function X(){let a=new B({port:T,resourcePath:"/UA/EmbeddedDemo",nodeset_filename:[F.standard],serverInfo:{applicationName:{text:"i3X Embedded Demo"}}});await a.initialize();let l=a.engine.addressSpace,o=l.getOwnNamespace(),t=o.addObject({organizedBy:l.rootFolder.objects,browseName:"SmartFactory",displayName:"Smart Factory"}),r=o.addObject({componentOf:t,browseName:"Pump",displayName:"Main Coolant Pump"}),S=o.addVariable({componentOf:r,browseName:"Temperature",displayName:"Temperature (\xB0C)",dataType:e.Double,value:new n({dataType:e.Double,value:35})}),g=o.addVariable({componentOf:r,browseName:"Pressure",displayName:"Pressure (bar)",dataType:e.Double,value:new n({dataType:e.Double,value:4.2})}),d=o.addVariable({componentOf:r,browseName:"FlowRate",displayName:"Flow Rate (L/min)",dataType:e.Double,value:new n({dataType:e.Double,value:120.5})}),i=o.addVariable({componentOf:r,browseName:"Running",displayName:"Running",dataType:e.Boolean,value:new n({dataType:e.Boolean,value:!0})}),p=o.addObject({componentOf:t,browseName:"Heater",displayName:"Process Heater"}),m=o.addVariable({componentOf:p,browseName:"HeaterOn",displayName:"Heater On/Off",dataType:e.Boolean,value:new n({dataType:e.Boolean,value:!0})}),P=o.addVariable({componentOf:p,browseName:"Temperature",displayName:"Temperature (\xB0C)",dataType:e.Double,value:new n({dataType:e.Double,value:180})}),z=o.addVariable({componentOf:p,browseName:"Setpoint",displayName:"Setpoint (\xB0C)",dataType:e.Double,value:new n({dataType:e.Double,value:200})}),V=o.addVariable({componentOf:p,browseName:"Power",displayName:"Power (%)",dataType:e.Double,value:new n({dataType:e.Double,value:85})}),O=o.addObject({componentOf:t,browseName:"Conveyor",displayName:"Assembly Conveyor"}),M=o.addVariable({componentOf:O,browseName:"Speed",displayName:"Speed (m/s)",dataType:e.Double,value:new n({dataType:e.Double,value:2.3})}),C=o.addVariable({componentOf:O,browseName:"ItemCount",displayName:"Items Processed",dataType:e.UInt32,value:new n({dataType:e.UInt32,value:8452})}),N=35,u=4.2,b=120.5,y=!0,w=180,h=85,v=2.3,D=8452;return setInterval(()=>{N+=(Math.random()-.48)*.5,u+=(Math.random()-.5)*.1,u=Math.max(3,Math.min(6,u)),b+=(Math.random()-.5)*2,b=Math.max(100,Math.min(140,b)),s(S,e.Double,N),s(g,e.Double,u),s(d,e.Double,b)},800),setInterval(()=>{y?(w+=(200-w)*.05+(Math.random()-.5)*.3,h=Math.max(0,Math.min(100,h+(Math.random()-.5)*5))):(w-=1.5+Math.random()*.5,h=0),s(P,e.Double,w),s(V,e.Double,h)},1e3),setInterval(()=>{y=!y,s(m,e.Boolean,y)},15e3),setInterval(()=>{D+=Math.floor(Math.random()*3),v+=(Math.random()-.5)*.1,v=Math.max(1.5,Math.min(3.5,v)),s(M,e.Double,v),s(C,e.UInt32,D)},1200),await a.start(),{server:a,addressSpace:l}}async function _(){let a=I;console.log(`
9
+ `),process.exit(0));var c=parseInt(f["rest-port"],10),T=parseInt(f["opcua-port"],10);function s(a,l,o){a.setValueFromSource(new n({dataType:l,value:o}))}async function X(){let a=new j({port:T,resourcePath:"/UA/EmbeddedDemo",nodeset_filename:[B.standard],serverInfo:{applicationName:{text:"i3X Embedded Demo"}}});await a.initialize();let l=a.engine.addressSpace,o=l.getOwnNamespace(),t=o.addObject({organizedBy:l.rootFolder.objects,browseName:"SmartFactory",displayName:"Smart Factory"}),r=o.addObject({componentOf:t,browseName:"Pump",displayName:"Main Coolant Pump"}),S=o.addVariable({componentOf:r,browseName:"Temperature",displayName:"Temperature (\xB0C)",dataType:e.Double,value:new n({dataType:e.Double,value:35})}),g=o.addVariable({componentOf:r,browseName:"Pressure",displayName:"Pressure (bar)",dataType:e.Double,value:new n({dataType:e.Double,value:4.2})}),d=o.addVariable({componentOf:r,browseName:"FlowRate",displayName:"Flow Rate (L/min)",dataType:e.Double,value:new n({dataType:e.Double,value:120.5})}),i=o.addVariable({componentOf:r,browseName:"Running",displayName:"Running",dataType:e.Boolean,value:new n({dataType:e.Boolean,value:!0})}),p=o.addObject({componentOf:t,browseName:"Heater",displayName:"Process Heater"}),m=o.addVariable({componentOf:p,browseName:"HeaterOn",displayName:"Heater On/Off",dataType:e.Boolean,value:new n({dataType:e.Boolean,value:!0})}),P=o.addVariable({componentOf:p,browseName:"Temperature",displayName:"Temperature (\xB0C)",dataType:e.Double,value:new n({dataType:e.Double,value:180})}),z=o.addVariable({componentOf:p,browseName:"Setpoint",displayName:"Setpoint (\xB0C)",dataType:e.Double,value:new n({dataType:e.Double,value:200})}),V=o.addVariable({componentOf:p,browseName:"Power",displayName:"Power (%)",dataType:e.Double,value:new n({dataType:e.Double,value:85})}),O=o.addObject({componentOf:t,browseName:"Conveyor",displayName:"Assembly Conveyor"}),M=o.addVariable({componentOf:O,browseName:"Speed",displayName:"Speed (m/s)",dataType:e.Double,value:new n({dataType:e.Double,value:2.3})}),C=o.addVariable({componentOf:O,browseName:"ItemCount",displayName:"Items Processed",dataType:e.UInt32,value:new n({dataType:e.UInt32,value:8452})}),N=35,u=4.2,b=120.5,y=!0,w=180,h=85,v=2.3,D=8452;return setInterval(()=>{N+=(Math.random()-.48)*.5,u+=(Math.random()-.5)*.1,u=Math.max(3,Math.min(6,u)),b+=(Math.random()-.5)*2,b=Math.max(100,Math.min(140,b)),s(S,e.Double,N),s(g,e.Double,u),s(d,e.Double,b)},800),setInterval(()=>{y?(w+=(200-w)*.05+(Math.random()-.5)*.3,h=Math.max(0,Math.min(100,h+(Math.random()-.5)*5))):(w-=1.5+Math.random()*.5,h=0),s(P,e.Double,w),s(V,e.Double,h)},1e3),setInterval(()=>{y=!y,s(m,e.Boolean,y)},15e3),setInterval(()=>{D+=Math.floor(Math.random()*3),v+=(Math.random()-.5)*.1,v=Math.max(1.5,Math.min(3.5,v)),s(M,e.Double,v),s(C,e.UInt32,D)},1200),await a.start(),{server:a,addressSpace:l}}async function _(){let a=A;console.log(`
10
10
  ${"\u2550".repeat(60)}`),console.log(" \u{1F3ED} i3X Embedded Demo \u2014 PseudoSession Connector"),console.log("\u2550".repeat(60)),console.log(`
11
11
  \u25B6 Starting OPC UA server...`);let{server:l,addressSpace:o}=await X();console.log(` \u2713 OPC UA binary endpoint at opc.tcp://localhost:${T}/UA/EmbeddedDemo`),console.log(`
12
- \u25B6 Connecting i3X via PseudoSession...`);let t=new x(o,a);await t.connect(),console.log(" \u2713 Connected \u2014 zero-network, in-process");let r=new U(t,a),S=new $(t,r,a),g=new A(t,r,a),d=new R(t,r,a,1);console.log(`
13
- \u25B6 Building i3X model from AddressSpace...`);let i=await r.preloadModel();console.log(` \u2713 ${i.nodesById.size} nodes, ${i.rootIds.length} roots, ${i.propertyToSource.size} properties`);let p=await E({dataSource:t,modelService:r,valueService:S,historyService:g,subscriptionService:d,logger:a});await p.listen({port:c,host:"127.0.0.1"}),console.log(`
12
+ \u25B6 Connecting i3X via PseudoSession...`);let t=new E(o,a);await t.connect(),console.log(" \u2713 Connected \u2014 zero-network, in-process");let r=new R(t,a),S=new x(t,r,a),g=new U(t,r,a),d=new $(t,r,a,1);console.log(`
13
+ \u25B6 Building i3X model from AddressSpace...`);let i=await r.preloadModel();console.log(` \u2713 ${i.nodesById.size} nodes, ${i.rootIds.length} roots, ${i.propertyToSource.size} properties`);let p=await F({dataSource:t,modelService:r,valueService:S,historyService:g,subscriptionService:d,logger:a});await p.listen({port:c,host:"127.0.0.1"}),console.log(`
14
14
  ${"\u2550".repeat(60)}`),console.log(` \u{1F680} i3X REST API ready at http://127.0.0.1:${c}`),console.log("\u2550".repeat(60)),console.log(`
15
15
  Try these:`),console.log(` curl http://localhost:${c}/health`),console.log(` curl http://localhost:${c}/v1/info`),console.log(` curl http://localhost:${c}/v1/namespaces`),console.log(` curl -X POST http://localhost:${c}/v1/objects/list`),console.log(`
16
16
  OPC UA clients can also connect to opc.tcp://localhost:${T}/UA/EmbeddedDemo`),console.log(`
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"mappings":"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","names":["consoleLogger","HistoryService","ModelService","SubscriptionService","ValueService","PseudoSessionDataSourceAdapter","createApp","DataType","nodesets","OPCUAServer","Variant","parseArgs","args","REST_PORT","OPCUA_PORT","setVar","v","dataType","val","createSampleServer","server","addressSpace","ns","factory","pump","pumpTempVar","pumpPressVar","pumpFlowVar","_pumpRunVar","heater","heaterOnVar","heaterTempVar","_heaterSetpointVar","heaterPowerVar","conveyor","convSpeedVar","itemCountVar","pumpTemp","pumpPressure","pumpFlowRate","heaterOn","heaterTemp","heaterPower","convSpeed","itemCount","main","logger","dataSource","modelService","valueService","historyService","subscriptionService","model","app","shutdown","err"]}
1
+ {"version":3,"sources":["../src/index.ts"],"mappings":"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","names":["parseArgs","consoleLogger","HistoryService","ModelService","SubscriptionService","ValueService","PseudoSessionDataSourceAdapter","createApp","DataType","nodesets","OPCUAServer","Variant","args","REST_PORT","OPCUA_PORT","setVar","v","dataType","val","createSampleServer","server","addressSpace","ns","factory","pump","pumpTempVar","pumpPressVar","pumpFlowVar","_pumpRunVar","heater","heaterOnVar","heaterTempVar","_heaterSetpointVar","heaterPowerVar","conveyor","convSpeedVar","itemCountVar","pumpTemp","pumpPressure","pumpFlowRate","heaterOn","heaterTemp","heaterPower","convSpeed","itemCount","main","logger","dataSource","modelService","valueService","historyService","subscriptionService","model","app","shutdown","err"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@node-i3x/demo-embedded",
3
- "version": "0.1.0",
3
+ "version": "0.2.3",
4
4
  "license": "AGPL-3.0-or-later OR LicenseRef-Sterfive-Commercial",
5
5
  "author": "Sterfive SAS <contact@sterfive.com> (https://sterfive.com)",
6
6
  "homepage": "https://sterfive.com",
@@ -14,7 +14,8 @@
14
14
  "main": "./dist/index.js",
15
15
  "types": "./dist/index.d.ts",
16
16
  "bin": {
17
- "i3x-demo": "./dist/index.js"
17
+ "i3x-demo": "./dist/index.js",
18
+ "i3x-demo-client": "./dist/client.js"
18
19
  },
19
20
  "exports": {
20
21
  ".": {
@@ -24,6 +25,9 @@
24
25
  "publishConfig": {
25
26
  "access": "public"
26
27
  },
28
+ "files": [
29
+ "dist"
30
+ ],
27
31
  "scripts": {
28
32
  "build": "tsup",
29
33
  "start": "npx tsx src/index.ts",
@@ -32,10 +36,10 @@
32
36
  "client": "npx tsx src/client.ts"
33
37
  },
34
38
  "dependencies": {
35
- "@node-i3x/core": "*",
36
- "@node-i3x/opcua-connector": "*",
37
- "@node-i3x/pseudo-session-connector": "*",
38
- "@node-i3x/rest-server": "*",
39
+ "@node-i3x/core": "0.2.3",
40
+ "@node-i3x/opcua-connector": "0.2.3",
41
+ "@node-i3x/pseudo-session-connector": "0.2.3",
42
+ "@node-i3x/rest-server": "0.2.3",
39
43
  "fastify": "^5.0.0",
40
44
  "@fastify/cors": "^11.0.0",
41
45
  "fastify-plugin": "^5.0.0",
package/src/client.ts DELETED
@@ -1,570 +0,0 @@
1
- // ─────────────────────────────────────────────────────────────
2
- // i3X REST Client — live dashboard with refreshing cards
3
- //
4
- // Run this AFTER the embedded demo is running:
5
- // npm run demo -w packages/demo-embedded (terminal 1)
6
- // npm run client -w packages/demo-embedded (terminal 2)
7
- // ─────────────────────────────────────────────────────────────
8
-
9
- import { parseArgs } from 'node:util';
10
-
11
- const { values: clientArgs } = parseArgs({
12
- options: {
13
- url: { type: 'string', default: process.env.I3X_URL ?? 'http://127.0.0.1:8080' },
14
- },
15
- });
16
-
17
- const BASE_URL = clientArgs.url!;
18
- const BASE = BASE_URL;
19
-
20
- // ── ANSI helpers ─────────────────────────────────────────────
21
-
22
- const ESC = '\x1b';
23
- const ansi = {
24
- clear: `${ESC}[2J${ESC}[H`,
25
- home: `${ESC}[H`,
26
- hideCursor: `${ESC}[?25l`,
27
- showCursor: `${ESC}[?25h`,
28
- bold: `${ESC}[1m`,
29
- dim: `${ESC}[2m`,
30
- reset: `${ESC}[0m`,
31
- // Foreground
32
- white: `${ESC}[97m`,
33
- gray: `${ESC}[90m`,
34
- cyan: `${ESC}[96m`,
35
- green: `${ESC}[92m`,
36
- red: `${ESC}[91m`,
37
- yellow: `${ESC}[93m`,
38
- blue: `${ESC}[94m`,
39
- magenta: `${ESC}[95m`,
40
- // Background
41
- bgDark: `${ESC}[48;5;236m`,
42
- bgCard: `${ESC}[48;5;238m`,
43
- bgHeader: `${ESC}[48;5;24m`,
44
- };
45
-
46
- // ── Fetch helpers ────────────────────────────────────────────
47
-
48
- async function get<T>(path: string): Promise<T> {
49
- const res = await fetch(`${BASE}${path}`);
50
- if (!res.ok) throw new Error(`GET ${path} → ${res.status}`);
51
- return res.json() as Promise<T>;
52
- }
53
-
54
- async function post<T>(path: string, body: unknown): Promise<T> {
55
- const res = await fetch(`${BASE}${path}`, {
56
- method: 'POST',
57
- headers: { 'Content-Type': 'application/json' },
58
- body: JSON.stringify(body),
59
- });
60
- if (!res.ok) throw new Error(`POST ${path} → ${res.status}`);
61
- return res.json() as Promise<T>;
62
- }
63
-
64
- // ── Types ────────────────────────────────────────────────────
65
-
66
- interface ObjectInstance {
67
- elementId: string;
68
- displayName: string;
69
- parentId: string | null;
70
- isComposition: boolean;
71
- }
72
-
73
- interface RelatedResult {
74
- sourceRelationship: string;
75
- object: ObjectInstance;
76
- }
77
-
78
- interface VQT {
79
- value: unknown;
80
- quality: string;
81
- timestamp: string;
82
- }
83
-
84
- interface ValueResult {
85
- isComposition?: boolean;
86
- components?: Record<string, VQT>;
87
- value?: unknown;
88
- quality?: string;
89
- timestamp?: string;
90
- }
91
-
92
- interface SubscriptionUpdate {
93
- sequenceNumber: number;
94
- elementId: string;
95
- value: ValueResult;
96
- quality: string;
97
- timestamp: string;
98
- }
99
-
100
- // ── State ────────────────────────────────────────────────────
101
-
102
- interface AssetCard {
103
- id: string;
104
- name: string;
105
- icon: string;
106
- properties: PropertyEntry[];
107
- }
108
-
109
- interface PropertyEntry {
110
- id: string;
111
- name: string;
112
- value: unknown;
113
- quality: string;
114
- timestamp: string;
115
- changed: boolean; // flash on recent change
116
- }
117
-
118
- const nameById = new Map<string, string>();
119
- const cards: AssetCard[] = [];
120
- let subId = '';
121
- let lastSeq = 0;
122
- let updateCount = 0;
123
- let totalChanges = 0;
124
- let serverName = '';
125
- let lastError = '';
126
-
127
- // ── Card width ───────────────────────────────────────────────
128
-
129
- const CARD_W = 44;
130
-
131
- // ── Box drawing ──────────────────────────────────────────────
132
-
133
- function boxTop(w: number): string {
134
- return `┌${'─'.repeat(w - 2)}┐`;
135
- }
136
- function boxMid(w: number): string {
137
- return `├${'─'.repeat(w - 2)}┤`;
138
- }
139
- function boxBot(w: number): string {
140
- return `└${'─'.repeat(w - 2)}┘`;
141
- }
142
- function boxRow(content: string, w: number): string {
143
- // Strip ANSI for length calculation
144
- // biome-ignore lint/suspicious/noControlCharactersInRegex: intentional ANSI escape stripping
145
- const visible = content.replace(/\x1b\[[0-9;]*m/g, '');
146
- const pad = Math.max(0, w - 4 - visible.length);
147
- return `│ ${content}${' '.repeat(pad)} │`;
148
- }
149
-
150
- // ── Discovery ────────────────────────────────────────────────
151
-
152
- async function discover(): Promise<string[]> {
153
- process.stdout.write(ansi.clear);
154
- process.stdout.write(ansi.hideCursor);
155
- process.stdout.write(
156
- `\n ${ansi.cyan}${ansi.bold}📡 Discovering i3X model...${ansi.reset}\n\n`,
157
- );
158
-
159
- const info = await get<{
160
- result: { serverName: string; specVersion: string };
161
- }>('/v1/info');
162
- serverName = info.result.serverName;
163
-
164
- // Root objects — skip OPC UA standard
165
- const roots = await get<{
166
- result: ObjectInstance[];
167
- }>('/v1/objects?root=true');
168
- const skipNames = ['Locations', 'Server', 'Aliases'];
169
- const userRoots = roots.result.filter((r) => !skipNames.includes(r.displayName));
170
-
171
- process.stdout.write(` Found ${userRoots.length} user-defined root(s)\n`);
172
-
173
- // Walk tree for each root
174
- const compositeIds: string[] = [];
175
- for (const root of userRoots) {
176
- await walkTree(root, compositeIds);
177
- }
178
-
179
- // Build cards for leaf assets (ones with properties)
180
- for (const card of cards) {
181
- process.stdout.write(` 📦 ${card.name} ` + `(${card.properties.length} props)\n`);
182
- }
183
-
184
- return compositeIds;
185
- }
186
-
187
- async function walkTree(obj: ObjectInstance, compositeIds: string[]): Promise<void> {
188
- nameById.set(obj.elementId, obj.displayName);
189
-
190
- if (!obj.isComposition) return;
191
-
192
- compositeIds.push(obj.id);
193
-
194
- const related = await post<{
195
- results: Array<{
196
- success: boolean;
197
- result: RelatedResult[];
198
- }>;
199
- }>('/v1/objects/related', {
200
- elementIds: [obj.elementId],
201
- });
202
-
203
- if (!related.results[0]?.success) return;
204
-
205
- const children = related.results[0]?.result.filter(
206
- (r) => r.sourceRelationship === 'HasComponent',
207
- );
208
-
209
- // Separate assets vs properties
210
- const childAssets = children.filter((c) => c.object.isComposition);
211
- const childProps = children.filter((c) => !c.object.isComposition);
212
-
213
- // If this node has properties, create a card
214
- if (childProps.length > 0) {
215
- const icon = iconForAsset(obj.displayName);
216
- const card: AssetCard = {
217
- id: obj.elementId,
218
- name: obj.displayName,
219
- icon,
220
- properties: childProps.map((c) => {
221
- nameById.set(c.object.elementId, c.object.displayName);
222
- return {
223
- id: c.object.elementId,
224
- name: c.object.displayName,
225
- value: '—',
226
- quality: 'Unknown',
227
- timestamp: '',
228
- changed: false,
229
- };
230
- }),
231
- };
232
- cards.push(card);
233
- }
234
-
235
- // Recurse into child assets
236
- for (const child of childAssets) {
237
- await walkTree(child.object, compositeIds);
238
- }
239
- }
240
-
241
- function iconForAsset(name: string): string {
242
- const n = name.toLowerCase();
243
- if (n.includes('pump')) return '💧';
244
- if (n.includes('heater')) return '🔥';
245
- if (n.includes('conveyor')) return '🏭';
246
- if (n.includes('factory')) return '🏗️';
247
- return '📦';
248
- }
249
-
250
- // ── Read initial values ──────────────────────────────────────
251
-
252
- async function readInitialValues(): Promise<void> {
253
- const ids = cards.map((c) => c.id);
254
- if (ids.length === 0) return;
255
-
256
- const values = await post<{
257
- results: Array<{
258
- success: boolean;
259
- elementId: string;
260
- result: ValueResult;
261
- }>;
262
- }>('/v1/objects/value', {
263
- elementIds: ids,
264
- maxDepth: 3,
265
- });
266
-
267
- for (const entry of values.results) {
268
- if (!entry.success) continue;
269
- if (!entry.result.isComposition) continue;
270
- if (!entry.result.components) continue;
271
-
272
- const card = cards.find((c) => c.id === entry.elementId);
273
- if (!card) continue;
274
-
275
- for (const prop of card.properties) {
276
- const vqt = entry.result.components[prop.id];
277
- if (vqt) {
278
- prop.value = vqt.value;
279
- prop.quality = vqt.quality;
280
- prop.timestamp = vqt.timestamp;
281
- }
282
- }
283
- }
284
- }
285
-
286
- // ── Create subscription ──────────────────────────────────────
287
-
288
- async function createSubscription(): Promise<void> {
289
- const ids = cards.map((c) => c.id);
290
- if (ids.length === 0) return;
291
-
292
- const createRes = await post<{
293
- result: { subscriptionId: string };
294
- }>('/v1/subscriptions', {
295
- clientId: 'dashboard-client',
296
- displayName: 'Dashboard Monitor',
297
- });
298
- subId = createRes.result.subscriptionId;
299
-
300
- await post('/v1/subscriptions/register', {
301
- subscriptionId: subId,
302
- elementIds: ids,
303
- maxDepth: 3,
304
- });
305
- }
306
-
307
- // ── Sync subscription updates ────────────────────────────────
308
-
309
- async function syncUpdates(): Promise<void> {
310
- try {
311
- const syncRes = await post<{
312
- result: SubscriptionUpdate[];
313
- }>('/v1/subscriptions/sync', {
314
- subscriptionId: subId,
315
- acknowledgeSequence: lastSeq,
316
- });
317
-
318
- const updates = syncRes.result;
319
- if (!updates || updates.length === 0) return;
320
-
321
- totalChanges += updates.length;
322
- updateCount++;
323
-
324
- // Clear all flash states
325
- for (const card of cards) {
326
- for (const prop of card.properties) {
327
- prop.changed = false;
328
- }
329
- }
330
-
331
- for (const u of updates) {
332
- if (u.sequenceNumber > lastSeq) {
333
- lastSeq = u.sequenceNumber;
334
- }
335
-
336
- if (!u.value?.isComposition || !u.value?.components) {
337
- continue;
338
- }
339
-
340
- const card = cards.find((c) => c.id === u.elementId);
341
- if (!card) continue;
342
-
343
- for (const [propId, vqt] of Object.entries(u.value.components)) {
344
- const prop = card.properties.find((p) => p.id === propId);
345
- if (prop) {
346
- prop.value = vqt.value;
347
- prop.quality = vqt.quality;
348
- prop.timestamp = vqt.timestamp;
349
- prop.changed = true;
350
- }
351
- }
352
- }
353
- lastError = '';
354
- } catch (err) {
355
- lastError = String(err);
356
- }
357
- }
358
-
359
- // ── Render ───────────────────────────────────────────────────
360
-
361
- function render(): void {
362
- const lines: string[] = [];
363
- const r = ansi.reset;
364
- const now = new Date().toLocaleTimeString();
365
-
366
- // Header bar
367
- lines.push('');
368
- lines.push(
369
- ` ${ansi.bgHeader}${ansi.white}${ansi.bold}` +
370
- ` 📡 i3X Dashboard — ${serverName} ` +
371
- `${r}` +
372
- ` ${ansi.dim}${now}${r}`,
373
- );
374
- lines.push('');
375
-
376
- // Status line
377
- const statusParts: string[] = [];
378
- statusParts.push(`${ansi.green}● Connected${r}`);
379
- statusParts.push(`${ansi.dim}Updates: ${updateCount}${r}`);
380
- statusParts.push(`${ansi.dim}Changes: ${totalChanges}${r}`);
381
- statusParts.push(`${ansi.dim}Seq: ${lastSeq}${r}`);
382
- lines.push(` ${statusParts.join(' │ ')}`);
383
- lines.push('');
384
-
385
- // Render cards in pairs (2 per row)
386
- for (let i = 0; i < cards.length; i += 2) {
387
- const left = renderCard(cards[i]!);
388
- const right = i + 1 < cards.length ? renderCard(cards[i + 1]!) : null;
389
-
390
- const maxLines = Math.max(left.length, right?.length ?? 0);
391
-
392
- for (let row = 0; row < maxLines; row++) {
393
- const l = left[row] ?? ' '.repeat(CARD_W);
394
- const rr = right ? (right[row] ?? ' '.repeat(CARD_W)) : '';
395
- lines.push(` ${l} ${rr}`);
396
- }
397
- lines.push('');
398
- }
399
-
400
- // Error line
401
- if (lastError) {
402
- lines.push(` ${ansi.red}⚠ ${lastError}${r}`);
403
- }
404
-
405
- // Footer
406
- lines.push(` ${ansi.dim}Press Ctrl+C to stop${r}`);
407
- lines.push('');
408
-
409
- // Write in one shot — move cursor home, overwrite
410
- process.stdout.write(ansi.home + lines.join('\n'));
411
- }
412
-
413
- function renderCard(card: AssetCard): string[] {
414
- const lines: string[] = [];
415
- const r = ansi.reset;
416
- const w = CARD_W;
417
-
418
- // Top border
419
- lines.push(`${ansi.dim}${boxTop(w)}${r}`);
420
-
421
- // Title
422
- const title = `${card.icon} ${ansi.bold}${ansi.cyan}` + `${card.name}${r}`;
423
- lines.push(`${ansi.dim}${boxRow(title, w)}${r}`);
424
- lines.push(`${ansi.dim}${boxMid(w)}${r}`);
425
-
426
- // Properties
427
- for (const prop of card.properties) {
428
- const label = cleanLabel(prop.name);
429
- const { text: valText, color } = formatPropValue(prop.value, prop.name);
430
-
431
- const flashColor = prop.changed ? ansi.yellow : ansi.dim;
432
-
433
- const line = `${flashColor}${label.padEnd(18)}${r} ` + `${color}${valText}${r}`;
434
-
435
- lines.push(`${ansi.dim}${boxRow(line, w)}${r}`);
436
- }
437
-
438
- // Bottom border
439
- lines.push(`${ansi.dim}${boxBot(w)}${r}`);
440
-
441
- return lines;
442
- }
443
-
444
- function cleanLabel(name: string): string {
445
- // Shorten common suffixes for compact display
446
- return name
447
- .replace(' (°C)', ' °C')
448
- .replace(' (bar)', ' bar')
449
- .replace(' (L/min)', ' L/min')
450
- .replace(' (m/s)', ' m/s')
451
- .replace(' (%)', ' %');
452
- }
453
-
454
- function formatPropValue(v: unknown, name: string): { text: string; color: string } {
455
- if (typeof v === 'boolean') {
456
- if (name.toLowerCase().includes('heater')) {
457
- return v
458
- ? { text: '🔥 ON', color: ansi.red }
459
- : { text: ' OFF', color: ansi.gray };
460
- }
461
- return v ? { text: '● ON', color: ansi.green } : { text: '○ OFF', color: ansi.gray };
462
- }
463
-
464
- if (typeof v === 'number') {
465
- const n = name.toLowerCase();
466
- let color = ansi.white;
467
-
468
- // Color-code by range
469
- if (n.includes('temperature') || n.includes('temp')) {
470
- if (v > 180) color = ansi.red;
471
- else if (v > 100) color = ansi.yellow;
472
- else color = ansi.green;
473
- } else if (n.includes('pressure')) {
474
- if (v > 5.5) color = ansi.red;
475
- else if (v > 4.5) color = ansi.yellow;
476
- else color = ansi.green;
477
- } else if (n.includes('power')) {
478
- if (v > 80) color = ansi.red;
479
- else if (v > 0) color = ansi.yellow;
480
- else color = ansi.gray;
481
- }
482
-
483
- const formatted = Number.isInteger(v) ? v.toLocaleString() : v.toFixed(2);
484
- return { text: formatted, color };
485
- }
486
-
487
- return {
488
- text: String(v ?? '—'),
489
- color: ansi.white,
490
- };
491
- }
492
-
493
- // ── Main ─────────────────────────────────────────────────────
494
-
495
- async function main() {
496
- // Check server
497
- try {
498
- await get('/health');
499
- } catch {
500
- console.error(`\n ❌ Cannot reach i3X server at ${BASE}`);
501
- console.error(
502
- ' Start the demo first:\n' + ' npm run demo -w packages/demo-embedded\n',
503
- );
504
- process.exit(1);
505
- }
506
-
507
- // Discovery phase (scrolling output)
508
- const _compositeIds = await discover();
509
-
510
- // Initial values
511
- process.stdout.write(`\n Reading initial values...\n`);
512
- await readInitialValues();
513
-
514
- // Subscription
515
- process.stdout.write(` Creating subscription...\n`);
516
- await createSubscription();
517
- process.stdout.write(` ✅ Monitoring ${cards.length} assets\n\n`);
518
-
519
- await sleep(1000);
520
-
521
- // Clear and enter dashboard mode
522
- process.stdout.write(ansi.clear);
523
- process.stdout.write(ansi.hideCursor);
524
-
525
- // Graceful shutdown
526
- const cleanup = async () => {
527
- process.stdout.write(ansi.showCursor);
528
- process.stdout.write('\n\n');
529
- if (subId) {
530
- try {
531
- await post('/v1/subscriptions/delete', {
532
- subscriptionIds: [subId],
533
- });
534
- } catch {
535
- /* ignore */
536
- }
537
- }
538
- console.log(' Subscription cleaned up. Bye!\n');
539
- process.exit(0);
540
- };
541
- process.on('SIGINT', () => {
542
- void cleanup();
543
- });
544
- process.on('SIGTERM', () => {
545
- void cleanup();
546
- });
547
-
548
- // Render loop
549
- render();
550
- let iteration = 0;
551
- while (iteration < 600) {
552
- // max ~20 minutes
553
- await sleep(2000);
554
- iteration++;
555
- await syncUpdates();
556
- render();
557
- }
558
-
559
- await cleanup();
560
- }
561
-
562
- function sleep(ms: number): Promise<void> {
563
- return new Promise((r) => setTimeout(r, ms));
564
- }
565
-
566
- main().catch((err) => {
567
- process.stdout.write(ansi.showCursor);
568
- console.error('Fatal:', err);
569
- process.exit(1);
570
- });
@@ -1,148 +0,0 @@
1
- // ─────────────────────────────────────────────────────────────
2
- // i3X Remote Demo (for comparison)
3
- //
4
- // Same OPC UA server, same REST API — but connected via
5
- // OPC UA binary transport (ClientSession over TCP).
6
- //
7
- // Run this side-by-side with the embedded demo to see
8
- // the architectural difference.
9
- // ─────────────────────────────────────────────────────────────
10
-
11
- import {
12
- consoleLogger,
13
- HistoryService,
14
- ModelService,
15
- SubscriptionService,
16
- ValueService,
17
- } from '@node-i3x/core';
18
- import { OpcUaClient, OpcUaDataSourceAdapter } from '@node-i3x/opcua-connector';
19
- import { createApp } from '@node-i3x/rest-server';
20
- import { DataType, nodesets, OPCUAServer, Variant } from 'node-opcua';
21
-
22
- const REST_PORT = 8080;
23
- const OPCUA_PORT = 48411;
24
-
25
- async function createSameServer() {
26
- const server = new OPCUAServer({
27
- port: OPCUA_PORT,
28
- resourcePath: '/UA/RemoteDemo',
29
- nodeset_filename: [nodesets.standard],
30
- });
31
- await server.initialize();
32
- const addressSpace = server.engine.addressSpace;
33
- if (!addressSpace) {
34
- throw new Error('Address space not initialized');
35
- }
36
- const ns = addressSpace.getOwnNamespace();
37
-
38
- const factory = ns.addObject({
39
- organizedBy: addressSpace.rootFolder.objects,
40
- browseName: 'SmartFactory',
41
- displayName: 'Smart Factory',
42
- });
43
- const pump = ns.addObject({
44
- componentOf: factory,
45
- browseName: 'Pump',
46
- displayName: 'Main Coolant Pump',
47
- });
48
- ns.addVariable({
49
- componentOf: pump,
50
- browseName: 'Temperature',
51
- dataType: DataType.Double,
52
- value: new Variant({
53
- dataType: DataType.Double,
54
- value: 35.0,
55
- }),
56
- });
57
- ns.addVariable({
58
- componentOf: pump,
59
- browseName: 'FlowRate',
60
- dataType: DataType.Double,
61
- value: new Variant({
62
- dataType: DataType.Double,
63
- value: 120.5,
64
- }),
65
- });
66
- ns.addVariable({
67
- componentOf: pump,
68
- browseName: 'Status',
69
- dataType: DataType.String,
70
- value: new Variant({
71
- dataType: DataType.String,
72
- value: 'Running',
73
- }),
74
- });
75
-
76
- await server.start();
77
- return server;
78
- }
79
-
80
- async function main() {
81
- const logger = consoleLogger;
82
-
83
- console.log(`\n${'═'.repeat(60)}`);
84
- console.log(' 🏭 i3X Remote Demo — OPC UA Binary Transport');
85
- console.log('═'.repeat(60));
86
-
87
- const server = await createSameServer();
88
- const endpointUrl = `opc.tcp://localhost:${OPCUA_PORT}/UA/RemoteDemo`;
89
- console.log(`\n OPC UA server at ${endpointUrl}`);
90
-
91
- // ┌──────────────────────────────────────────────────────┐
92
- // │ REMOTE path: connect via OPC UA binary protocol │
93
- // │ Requires TCP connection, serialization, etc. │
94
- // └──────────────────────────────────────────────────────┘
95
- const client = new OpcUaClient(
96
- {
97
- endpointUrl,
98
- securityMode: 'None',
99
- optimizedClient: 'disabled',
100
- },
101
- logger,
102
- );
103
- const dataSource = new OpcUaDataSourceAdapter(client, logger);
104
- await dataSource.connect();
105
-
106
- const modelService = new ModelService(dataSource, logger);
107
- const valueService = new ValueService(dataSource, modelService, logger);
108
- const historyService = new HistoryService(dataSource, modelService, logger);
109
- const subscriptionService = new SubscriptionService(
110
- dataSource,
111
- modelService,
112
- logger,
113
- 1,
114
- );
115
-
116
- const model = await modelService.preloadModel();
117
- console.log(
118
- ` Model: ${model.nodesById.size} nodes, ` + `${model.rootIds.length} roots`,
119
- );
120
-
121
- const app = await createApp({
122
- dataSource,
123
- modelService,
124
- valueService,
125
- historyService,
126
- subscriptionService,
127
- logger,
128
- });
129
- await app.listen({ port: REST_PORT, host: '127.0.0.1' });
130
-
131
- console.log(`\n 🚀 REST API at http://127.0.0.1:${REST_PORT}`);
132
- console.log(' Press Ctrl+C to stop.\n');
133
-
134
- const shutdown = async () => {
135
- await app.close();
136
- await subscriptionService.close();
137
- await dataSource.disconnect();
138
- await server.shutdown(500);
139
- process.exit(0);
140
- };
141
- process.on('SIGINT', shutdown);
142
- process.on('SIGTERM', shutdown);
143
- }
144
-
145
- main().catch((err) => {
146
- console.error('Fatal:', err);
147
- process.exit(1);
148
- });
package/src/index.ts DELETED
@@ -1,350 +0,0 @@
1
- // ─────────────────────────────────────────────────────────────
2
- // i3X Embedded Demo
3
- //
4
- // Creates an OPC UA server + i3X REST API in a SINGLE process.
5
- // No TCP round-trip — PseudoSession talks directly to the
6
- // AddressSpace in memory.
7
- // ─────────────────────────────────────────────────────────────
8
-
9
- import {
10
- consoleLogger,
11
- HistoryService,
12
- ModelService,
13
- SubscriptionService,
14
- ValueService,
15
- } from '@node-i3x/core';
16
- import { PseudoSessionDataSourceAdapter } from '@node-i3x/pseudo-session-connector';
17
- import { createApp } from '@node-i3x/rest-server';
18
- import { DataType, nodesets, OPCUAServer, type UAVariable, Variant } from 'node-opcua';
19
- import { parseArgs } from 'node:util';
20
-
21
- const { values: args } = parseArgs({
22
- options: {
23
- 'rest-port': { type: 'string', default: '8080' },
24
- 'opcua-port': { type: 'string', default: '48410' },
25
- help: { type: 'boolean', short: 'h', default: false },
26
- },
27
- });
28
-
29
- if (args.help) {
30
- console.log(`
31
- Usage: i3x-demo [options]
32
-
33
- Options:
34
- --rest-port <port> REST API port (default: 8080)
35
- --opcua-port <port> OPC UA server port (default: 48410)
36
- -h, --help Show this help
37
- `);
38
- process.exit(0);
39
- }
40
-
41
- const REST_PORT = parseInt(args['rest-port']!, 10);
42
- const OPCUA_PORT = parseInt(args['opcua-port']!, 10);
43
-
44
- // ── Helper: update a variable and fire value_changed ──────
45
-
46
- function setVar(v: UAVariable, dataType: DataType, val: unknown) {
47
- v.setValueFromSource(new Variant({ dataType, value: val }));
48
- }
49
-
50
- // ── 1. Create an OPC UA server with sample nodes ─────────
51
-
52
- async function createSampleServer() {
53
- const server = new OPCUAServer({
54
- port: OPCUA_PORT,
55
- resourcePath: '/UA/EmbeddedDemo',
56
- nodeset_filename: [nodesets.standard],
57
- serverInfo: {
58
- applicationName: { text: 'i3X Embedded Demo' },
59
- },
60
- });
61
-
62
- await server.initialize();
63
- const addressSpace = server.engine.addressSpace!;
64
- const ns = addressSpace.getOwnNamespace();
65
-
66
- // ── Factory floor ────────────────────────────────────
67
- const factory = ns.addObject({
68
- organizedBy: addressSpace.rootFolder.objects,
69
- browseName: 'SmartFactory',
70
- displayName: 'Smart Factory',
71
- });
72
-
73
- // ── Pump ─────────────────────────────────────────────
74
- const pump = ns.addObject({
75
- componentOf: factory,
76
- browseName: 'Pump',
77
- displayName: 'Main Coolant Pump',
78
- });
79
-
80
- const pumpTempVar = ns.addVariable({
81
- componentOf: pump,
82
- browseName: 'Temperature',
83
- displayName: 'Temperature (°C)',
84
- dataType: DataType.Double,
85
- value: new Variant({
86
- dataType: DataType.Double,
87
- value: 35.0,
88
- }),
89
- });
90
-
91
- const pumpPressVar = ns.addVariable({
92
- componentOf: pump,
93
- browseName: 'Pressure',
94
- displayName: 'Pressure (bar)',
95
- dataType: DataType.Double,
96
- value: new Variant({
97
- dataType: DataType.Double,
98
- value: 4.2,
99
- }),
100
- });
101
-
102
- const pumpFlowVar = ns.addVariable({
103
- componentOf: pump,
104
- browseName: 'FlowRate',
105
- displayName: 'Flow Rate (L/min)',
106
- dataType: DataType.Double,
107
- value: new Variant({
108
- dataType: DataType.Double,
109
- value: 120.5,
110
- }),
111
- });
112
-
113
- const _pumpRunVar = ns.addVariable({
114
- componentOf: pump,
115
- browseName: 'Running',
116
- displayName: 'Running',
117
- dataType: DataType.Boolean,
118
- value: new Variant({
119
- dataType: DataType.Boolean,
120
- value: true,
121
- }),
122
- });
123
-
124
- // ── Heater ───────────────────────────────────────────
125
- const heater = ns.addObject({
126
- componentOf: factory,
127
- browseName: 'Heater',
128
- displayName: 'Process Heater',
129
- });
130
-
131
- const heaterOnVar = ns.addVariable({
132
- componentOf: heater,
133
- browseName: 'HeaterOn',
134
- displayName: 'Heater On/Off',
135
- dataType: DataType.Boolean,
136
- value: new Variant({
137
- dataType: DataType.Boolean,
138
- value: true,
139
- }),
140
- });
141
-
142
- const heaterTempVar = ns.addVariable({
143
- componentOf: heater,
144
- browseName: 'Temperature',
145
- displayName: 'Temperature (°C)',
146
- dataType: DataType.Double,
147
- value: new Variant({
148
- dataType: DataType.Double,
149
- value: 180.0,
150
- }),
151
- });
152
-
153
- const _heaterSetpointVar = ns.addVariable({
154
- componentOf: heater,
155
- browseName: 'Setpoint',
156
- displayName: 'Setpoint (°C)',
157
- dataType: DataType.Double,
158
- value: new Variant({
159
- dataType: DataType.Double,
160
- value: 200.0,
161
- }),
162
- });
163
-
164
- const heaterPowerVar = ns.addVariable({
165
- componentOf: heater,
166
- browseName: 'Power',
167
- displayName: 'Power (%)',
168
- dataType: DataType.Double,
169
- value: new Variant({
170
- dataType: DataType.Double,
171
- value: 85.0,
172
- }),
173
- });
174
-
175
- // ── Conveyor ─────────────────────────────────────────
176
- const conveyor = ns.addObject({
177
- componentOf: factory,
178
- browseName: 'Conveyor',
179
- displayName: 'Assembly Conveyor',
180
- });
181
-
182
- const convSpeedVar = ns.addVariable({
183
- componentOf: conveyor,
184
- browseName: 'Speed',
185
- displayName: 'Speed (m/s)',
186
- dataType: DataType.Double,
187
- value: new Variant({
188
- dataType: DataType.Double,
189
- value: 2.3,
190
- }),
191
- });
192
-
193
- const itemCountVar = ns.addVariable({
194
- componentOf: conveyor,
195
- browseName: 'ItemCount',
196
- displayName: 'Items Processed',
197
- dataType: DataType.UInt32,
198
- value: new Variant({
199
- dataType: DataType.UInt32,
200
- value: 8452,
201
- }),
202
- });
203
-
204
- // ── Simulation (setValueFromSource → fires events) ───
205
-
206
- // Mutable state for simulation
207
- let pumpTemp = 35.0;
208
- let pumpPressure = 4.2;
209
- let pumpFlowRate = 120.5;
210
- let heaterOn = true;
211
- let heaterTemp = 180.0;
212
- let heaterPower = 85.0;
213
- let convSpeed = 2.3;
214
- let itemCount = 8452;
215
-
216
- // Pump: temperature, pressure, flow drift every 800ms
217
- setInterval(() => {
218
- pumpTemp += (Math.random() - 0.48) * 0.5;
219
- pumpPressure += (Math.random() - 0.5) * 0.1;
220
- pumpPressure = Math.max(3.0, Math.min(6.0, pumpPressure));
221
- pumpFlowRate += (Math.random() - 0.5) * 2.0;
222
- pumpFlowRate = Math.max(100, Math.min(140, pumpFlowRate));
223
-
224
- setVar(pumpTempVar, DataType.Double, pumpTemp);
225
- setVar(pumpPressVar, DataType.Double, pumpPressure);
226
- setVar(pumpFlowVar, DataType.Double, pumpFlowRate);
227
- }, 800);
228
-
229
- // Heater: temp tracks setpoint, power varies
230
- setInterval(() => {
231
- if (heaterOn) {
232
- heaterTemp += (200.0 - heaterTemp) * 0.05 + (Math.random() - 0.5) * 0.3;
233
- heaterPower = Math.max(0, Math.min(100, heaterPower + (Math.random() - 0.5) * 5));
234
- } else {
235
- heaterTemp -= 1.5 + Math.random() * 0.5;
236
- heaterPower = 0;
237
- }
238
- setVar(heaterTempVar, DataType.Double, heaterTemp);
239
- setVar(heaterPowerVar, DataType.Double, heaterPower);
240
- }, 1000);
241
-
242
- // Toggle heater every ~15 seconds
243
- setInterval(() => {
244
- heaterOn = !heaterOn;
245
- setVar(heaterOnVar, DataType.Boolean, heaterOn);
246
- }, 15_000);
247
-
248
- // Conveyor: items increase, speed varies
249
- setInterval(() => {
250
- itemCount += Math.floor(Math.random() * 3);
251
- convSpeed += (Math.random() - 0.5) * 0.1;
252
- convSpeed = Math.max(1.5, Math.min(3.5, convSpeed));
253
-
254
- setVar(convSpeedVar, DataType.Double, convSpeed);
255
- setVar(itemCountVar, DataType.UInt32, itemCount);
256
- }, 1200);
257
-
258
- await server.start();
259
-
260
- return { server, addressSpace };
261
- }
262
-
263
- // ── 2. Wire everything together ──────────────────────────
264
-
265
- async function main() {
266
- const logger = consoleLogger;
267
-
268
- console.log(`\n${'═'.repeat(60)}`);
269
- console.log(' 🏭 i3X Embedded Demo — PseudoSession Connector');
270
- console.log('═'.repeat(60));
271
-
272
- // Create the OPC UA server
273
- console.log('\n▶ Starting OPC UA server...');
274
- const { server, addressSpace } = await createSampleServer();
275
- console.log(
276
- ` ✓ OPC UA binary endpoint at ` +
277
- `opc.tcp://localhost:${OPCUA_PORT}/UA/EmbeddedDemo`,
278
- );
279
-
280
- // ┌──────────────────────────────────────────────────────┐
281
- // │ THIS IS THE KEY PART — 3 lines to connect i3X │
282
- // │ directly to the AddressSpace, no network needed. │
283
- // └──────────────────────────────────────────────────────┘
284
- console.log('\n▶ Connecting i3X via PseudoSession...');
285
- const dataSource = new PseudoSessionDataSourceAdapter(addressSpace, logger);
286
- await dataSource.connect();
287
- console.log(' ✓ Connected — zero-network, in-process');
288
-
289
- // Domain services (identical to the remote OPC UA path)
290
- const modelService = new ModelService(dataSource, logger);
291
- const valueService = new ValueService(dataSource, modelService, logger);
292
- const historyService = new HistoryService(dataSource, modelService, logger);
293
- const subscriptionService = new SubscriptionService(
294
- dataSource,
295
- modelService,
296
- logger,
297
- 1,
298
- );
299
-
300
- // Preload the model
301
- console.log('\n▶ Building i3X model from AddressSpace...');
302
- const model = await modelService.preloadModel();
303
- console.log(
304
- ` ✓ ${model.nodesById.size} nodes, ` +
305
- `${model.rootIds.length} roots, ` +
306
- `${model.propertyToSource.size} properties`,
307
- );
308
-
309
- // Start REST server
310
- const app = await createApp({
311
- dataSource,
312
- modelService,
313
- valueService,
314
- historyService,
315
- subscriptionService,
316
- logger,
317
- });
318
- await app.listen({ port: REST_PORT, host: '127.0.0.1' });
319
-
320
- console.log(`\n${'═'.repeat(60)}`);
321
- console.log(` 🚀 i3X REST API ready at http://127.0.0.1:${REST_PORT}`);
322
- console.log('═'.repeat(60));
323
- console.log('\n Try these:');
324
- console.log(` curl http://localhost:${REST_PORT}/health`);
325
- console.log(` curl http://localhost:${REST_PORT}/v1/info`);
326
- console.log(` curl http://localhost:${REST_PORT}/v1/namespaces`);
327
- console.log(` curl -X POST http://localhost:${REST_PORT}/v1/objects/list`);
328
- console.log(
329
- `\n OPC UA clients can also connect to ` +
330
- `opc.tcp://localhost:${OPCUA_PORT}/UA/EmbeddedDemo`,
331
- );
332
- console.log('\n Press Ctrl+C to stop.\n');
333
-
334
- // Graceful shutdown
335
- const shutdown = async () => {
336
- console.log('\n\nShutting down...');
337
- await app.close();
338
- await subscriptionService.close();
339
- await dataSource.disconnect();
340
- await server.shutdown(500);
341
- process.exit(0);
342
- };
343
- process.on('SIGINT', shutdown);
344
- process.on('SIGTERM', shutdown);
345
- }
346
-
347
- main().catch((err) => {
348
- console.error('Fatal:', err);
349
- process.exit(1);
350
- });
package/tsconfig.json DELETED
@@ -1,13 +0,0 @@
1
- {
2
- "extends": "../../tsconfig.base.json",
3
- "compilerOptions": {
4
- "outDir": "./dist",
5
- "rootDir": "./src"
6
- },
7
- "include": ["src/**/*"],
8
- "references": [
9
- { "path": "../core" },
10
- { "path": "../pseudo-session-connector" },
11
- { "path": "../rest-server" }
12
- ]
13
- }
package/tsup.config.ts DELETED
@@ -1,41 +0,0 @@
1
- import { defineConfig } from 'tsup';
2
-
3
- export default defineConfig([
4
- {
5
- entry: ['src/index.ts'],
6
- format: ['esm'],
7
- minify: true,
8
- sourcemap: true,
9
- esbuildOptions(options) {
10
- options.sourcesContent = false;
11
- },
12
- clean: true,
13
- external: [
14
- /^@node-i3x\//,
15
- /^node-opcua/,
16
- /^fastify/,
17
- '@fastify/cors',
18
- ],
19
- banner: {
20
- js: '#!/usr/bin/env node',
21
- },
22
- },
23
- {
24
- entry: ['src/client.ts'],
25
- format: ['esm'],
26
- minify: true,
27
- sourcemap: true,
28
- esbuildOptions(options) {
29
- options.sourcesContent = false;
30
- },
31
- external: [
32
- /^@node-i3x\//,
33
- /^node-opcua/,
34
- /^fastify/,
35
- '@fastify/cors',
36
- ],
37
- banner: {
38
- js: '#!/usr/bin/env node',
39
- },
40
- },
41
- ]);