1414 ********************************************************************************/
1515
1616/* eslint no-console: "off" */
17-
17+ import util from "util" ;
1818import { Servient } from "@node-wot/core" ;
1919import { OPCUAClientFactory } from "@node-wot/binding-opcua" ;
2020import { thingDescription } from "./opcua-coffee-machine-thing-description" ;
@@ -25,37 +25,156 @@ const pause = async (ms: number) => new Promise((resolve) => setTimeout(resolve,
2525 servient . addClientFactory ( new OPCUAClientFactory ( ) ) ;
2626
2727 const wot = await servient . start ( ) ;
28+
2829 const thing = await wot . consume ( thingDescription ) ;
2930
31+ let lastTemperature = NaN ;
32+ let lastWaterTankLevel = NaN ;
33+ let lastCoffeeBeanLevel = NaN ;
34+ let lastCurrentState = NaN ;
35+ let lastGrindingDuration = NaN ;
36+ let lastGrinderStatus = NaN ;
37+ let lastHeaterStatus = NaN ;
38+ let lastPumpStatus = NaN ;
39+ let lastValveStatus = NaN ;
40+
41+ const recordedActions : string [ ] = [ ] ;
42+ const recordAction = ( actionName : string ) => {
43+ recordedActions . push ( `${ new Date ( ) . toISOString ( ) } - ${ actionName } ` ) ;
44+ } ;
45+ process . stdout . write ( "\x1Bc" ) ; // clear console
46+ process . stdout . write ( "\x1B[?25l" ) ; // hide cursor
47+ const currentStateEnum = [ "Off" , "Standby" , "Error" , "Cleaning" , "Serving Coffee" , "Under Maintenance" ] ;
48+ const grinderStates = [ "Off" , "On" , "Jammed" , "Malfunctioning" ] ;
49+ const heaterStates = [ "Off" , "Heating" , "Ready" , "Malfunctioning" ] ;
50+ const pumpStates = [ "Off" , "On" , "Malfunctioning" ] ;
51+ const valveStates = [ "Open" , "Opening" , "Close" , "Closing" , "Malfunctioning" ] ;
52+
53+ const waitingMachineCoffeeStandByState = async ( ) => {
54+ await pause ( 1000 ) ;
55+ let state = lastCurrentState ;
56+ while ( state !== 1 ) {
57+ // Standby
58+ await pause ( 1000 ) ;
59+ state = lastCurrentState ;
60+ }
61+ } ;
62+ const writeLine = ( ...args : unknown [ ] ) => {
63+ process . stdout . write ( util . format ( ...args ) + " \n" ) ;
64+ } ;
65+ const displayOnlineStatus = ( ) => {
66+ process . stdout . write ( "\x1B[1;1H" ) ; // move cursor to top left
67+ writeLine ( `======== Coffee Machine Status ======== ${ new Date ( ) . toISOString ( ) } ` ) ;
68+ writeLine (
69+ ` 🔄 Current State : ${
70+ isNaN ( lastCurrentState ) ? "n/a" : ( currentStateEnum [ lastCurrentState ] ?? lastCurrentState )
71+ } `
72+ ) ;
73+ writeLine (
74+ ` 🔥 Heater Status : ${
75+ isNaN ( lastHeaterStatus ) ? "n/a" : ( heaterStates [ lastHeaterStatus ] ?? lastHeaterStatus )
76+ } `
77+ ) ;
78+ writeLine (
79+ ` 🌡️ Boiler Temperature : ${ isNaN ( lastTemperature ) ? "n/a" : lastTemperature . toFixed ( 2 ) + " °C" } `
80+ ) ;
81+ writeLine (
82+ ` 🚰 Pump Status : ${
83+ isNaN ( lastPumpStatus ) ? "n/a" : ( pumpStates [ lastPumpStatus ] ?? lastPumpStatus )
84+ } `
85+ ) ;
86+ writeLine (
87+ ` 🚪 Valve Status : ${
88+ isNaN ( lastValveStatus ) ? "n/a" : ( valveStates [ lastValveStatus ] ?? lastValveStatus )
89+ } `
90+ ) ;
91+ writeLine (
92+ ` 💧 Water Tank Level : ${ isNaN ( lastWaterTankLevel ) ? "n/a" : lastWaterTankLevel . toFixed ( 2 ) + " ml" } `
93+ ) ;
94+ writeLine (
95+ ` ⚙️ Grinder Status : ${
96+ isNaN ( lastGrinderStatus ) ? "n/a" : ( grinderStates [ lastGrinderStatus ] ?? lastGrinderStatus )
97+ } `
98+ ) ;
99+ writeLine (
100+ ` ⏱️ Grinding Duration : ${
101+ isNaN ( lastGrindingDuration ) ? "n/a" : lastGrindingDuration . toFixed ( 2 ) + " s"
102+ } `
103+ ) ;
104+ writeLine (
105+ ` ☕ Coffee Bean Level : ${ isNaN ( lastCoffeeBeanLevel ) ? "n/a" : lastCoffeeBeanLevel . toFixed ( 2 ) + " g" } `
106+ ) ;
107+ writeLine ( "========================================" ) ;
108+ writeLine ( "---- Recorded Actions (last 5) ----" ) ;
109+ recordedActions
110+ . slice ( - 5 )
111+ . forEach ( ( action ) => writeLine ( action + " " ) ) ;
112+ writeLine ( "-----------------------------------" ) ;
113+ } ;
30114 try {
31- thing
32- . observeProperty ( "waterTankLevel" , async ( data ) => {
33- const waterTankLevel = await data . value ( ) ;
34- console . log ( "------------------------------" ) ;
35- console . log ( "tankLevel : " , waterTankLevel , "ml" ) ;
36- console . log ( "------------------------------" ) ;
37- } )
38- . catch ( ( err ) => {
39- console . error ( "Error observing waterTankLevel property:" , err ) ;
40- } ) ;
41- thing
42- . observeProperty ( "coffeeBeanLevel" , async ( data ) => {
43- const coffeBeanLevel = await data . value ( ) ;
44- console . log ( "------------------------------" ) ;
45- console . log ( "bean level : " , coffeBeanLevel , "g" ) ;
46- console . log ( "------------------------------" ) ;
47- } )
48- . catch ( ( err ) => {
49- console . error ( "Error observing coffeeBeanLevel property:" , err ) ;
50- } ) ;
115+ await thing . observeProperty ( "waterTankLevel" , async ( data ) => {
116+ lastWaterTankLevel = ( await data . value ( ) ) as number ;
117+ displayOnlineStatus ( ) ;
118+ } ) ;
119+ await thing . observeProperty ( "coffeeBeanLevel" , async ( data ) => {
120+ lastCoffeeBeanLevel = ( await data . value ( ) ) as number ;
121+ displayOnlineStatus ( ) ;
122+ } ) ;
123+ await thing . observeProperty ( "temperature" , async ( data ) => {
124+ lastTemperature = ( await data . value ( ) ) as number ;
125+ displayOnlineStatus ( ) ;
126+ } ) ;
127+ await thing . observeProperty ( "currentState" , async ( data ) => {
128+ lastCurrentState = ( await data . value ( ) ) as number ;
129+ displayOnlineStatus ( ) ;
130+ } ) ;
131+ await thing . observeProperty ( "grinderStatus" , async ( data ) => {
132+ lastGrinderStatus = ( await data . value ( ) ) as number ;
133+ displayOnlineStatus ( ) ;
134+ } ) ;
135+ await thing . observeProperty ( "grindingDuration" , async ( data ) => {
136+ lastGrindingDuration = ( await data . value ( ) ) as number ;
137+ displayOnlineStatus ( ) ;
138+ } ) ;
139+ await thing . observeProperty ( "heaterStatus" , async ( data ) => {
140+ lastHeaterStatus = ( await data . value ( ) ) as number ;
141+ displayOnlineStatus ( ) ;
142+ } ) ;
143+ await thing . observeProperty ( "pumpStatus" , async ( data ) => {
144+ lastPumpStatus = ( await data . value ( ) ) as number ;
145+ displayOnlineStatus ( ) ;
146+ } ) ;
147+ await thing . observeProperty ( "valveStatus" , async ( data ) => {
148+ lastValveStatus = ( await data . value ( ) ) as number ;
149+ displayOnlineStatus ( ) ;
150+ } ) ;
151+
152+ // give some time to gather initial values
153+ await pause ( 2000 ) ;
154+ await waitingMachineCoffeeStandByState ( ) ;
155+ recordAction ( "Machine is ready !" ) ;
156+
157+ await pause ( 10000 ) ;
158+
159+ recordAction ( "Invoking brewCoffee(Mocha) action..." ) ;
160+ await thing . invokeAction ( "brewCoffee" , { RecipeName : "Mocha" } ) ;
161+ await waitingMachineCoffeeStandByState ( ) ;
162+ recordAction ( "Coffee is ready !" ) ;
163+
164+ await pause ( 10000 ) ;
165+
166+ recordAction ( "Invoking brewCoffee(Americano) action..." ) ;
167+ await thing . invokeAction ( "brewCoffee" , { RecipeName : "Americano" } ) ;
168+ await waitingMachineCoffeeStandByState ( ) ;
169+ recordAction ( "Coffee is ready !" ) ;
51170
52- await thing . invokeAction ( "brewCoffee" , { CoffeeType : 1 } ) ;
53- await pause ( 5000 ) ;
54- await thing . invokeAction ( "brewCoffee" , { CoffeeType : 0 } ) ;
55- await pause ( 5000 ) ;
171+ await pause ( 10000 ) ;
56172
173+ recordAction ( "Invoking fillTank action..." ) ;
57174 await thing . invokeAction ( "fillTank" ) ;
58- await pause ( 5000 ) ;
175+ await waitingMachineCoffeeStandByState ( ) ;
176+ recordAction ( "Tank is refilled !" ) ;
177+ recordAction ( "Done !" ) ;
59178 } finally {
60179 await servient . shutdown ( ) ;
61180 }
0 commit comments