Just created v2 of the Traffic Light System with enum types for 'STATES' and 'STATE_TABLE'.
Also using separate output ports for the three traffic lights and msg.delay for the FSM Timer.
[{"id":"b5a1333e3bb6b1d0","type":"tab","label":"Statemachine Trafficlight","disabled":false,"info":"","env":[]},{"id":"93814d1a6470edbc","type":"function","z":"b5a1333e3bb6b1d0","name":"Decode RED light","func":"var fsm_state = flow.get(\"state_counter\");\n\nif (fsm_state === 0 || fsm_state == 1)\n {msg.payload = 1;\n node.status({fill:\"red\",shape:\"dot\",text:\"Red ON\"});\n }\n \nelse\n {msg.payload = 0;\n node.status({});\n }\n\nreturn msg;","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":990,"y":60,"wires":[[]]},{"id":"db12c168fa131df2","type":"function","z":"b5a1333e3bb6b1d0","name":"Decode YELLOW light","func":"var fsm_state = flow.get(\"state_counter\");\n\nif (fsm_state == 1 || fsm_state == 3)\n {msg.payload = 1;\n node.status({fill:\"yellow\",shape:\"dot\",text:\"Yellow ON\"});\n }\nelse\n {msg.payload = 0;\n node.status({});}\n\nreturn msg;","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1000,"y":120,"wires":[[]]},{"id":"a162a116a95762d3","type":"function","z":"b5a1333e3bb6b1d0","name":"Decode GREEN light","func":"var fsm_state = flow.get(\"state_counter\");\n\nif (fsm_state == 2)\n {msg.payload = 1;\n node.status({fill:\"green\",shape:\"dot\",text:\"Green ON\"});\n }\nelse\n {msg.payload = 0;\n node.status({});\n }\n\nreturn msg;","outputs":1,"noerr":0,"x":1000,"y":180,"wires":[[]]},{"id":"1b98b5e06bd62acb","type":"inject","z":"b5a1333e3bb6b1d0","name":"Start & Stop Toggle","props":[{"p":"payload"},{"p":"delay","v":"1","vt":"num"}],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"1","payloadType":"num","x":190,"y":160,"wires":[["5213c067599bf3b1","958e1a7760c9bf69"]]},{"id":"5213c067599bf3b1","type":"function","z":"b5a1333e3bb6b1d0","name":"Start & Stop Indicator","func":"var status = flow.get(\"status\") || \"disable\";\n\nif (status == \"disable\") {\n flow.set(\"status\", \"enable\");\n node.status({text:\"Running\"});\n}\nelse {\n flow.set(\"status\", \"disable\");\n node.status({text:\"Stopped\"});\n}\n","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":440,"y":80,"wires":[[]]},{"id":"6c1d0d61a5b43642","type":"function","z":"b5a1333e3bb6b1d0","name":"EnableFSM","func":"var status = flow.get(\"status\") || \"disable\";\nif (status == \"enable\") {\n node.status({text:\"Enabled\"});\n return msg;\n}\nelse {\n node.status({text:\"State = Disabled\"});\n return null;\n}\n","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":590,"y":160,"wires":[["853d0f129c7a0e22"]]},{"id":"958e1a7760c9bf69","type":"delay","z":"b5a1333e3bb6b1d0","name":"FSM Timer","pauseType":"delayv","timeout":"1","timeoutUnits":"milliseconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":410,"y":160,"wires":[["6c1d0d61a5b43642"]]},{"id":"853d0f129c7a0e22","type":"function","z":"b5a1333e3bb6b1d0","name":"FSM-v2","func":"// ****************\n// * State Enum *\n// ****************\nconst STATES = {\n RED: 0,\n RED_AMBER: 1,\n GREEN: 2,\n AMBER: 3\n};\n\n// ****************\n// * State Config *\n// ****************\nconst STATE_TABLE = {\n [STATES.RED]: { delay: 1000, lamps: [1, 0, 0], next: STATES.RED_AMBER },\n [STATES.RED_AMBER]: { delay: 500, lamps: [1, 1, 0], next: STATES.GREEN },\n [STATES.GREEN]: { delay: 1000, lamps: [0, 0, 1], next: STATES.AMBER },\n [STATES.AMBER]: { delay: 1000, lamps: [0, 1, 0], next: STATES.RED }\n};\n\n// ***************\n// * Get State *\n// ***************\nlet state = flow.get(\"state_counter\") ?? STATES.RED;\nconst cfg = STATE_TABLE[state];\n\n// ***************\n// * Set Outputs *\n// ***************\nconst red = { payload: cfg.lamps[0] }; // Output 1: red\nconst amber = { payload: cfg.lamps[1] }; // Output 2: amber\nconst green = { payload: cfg.lamps[2] }; // Output 3: green\nconst delayMsg = { delay: cfg.delay }; // Output 4: delay value ONLY in msg.delay\n\n// ***************\n// * Update State*\n// ***************\nflow.set(\"state_counter\", cfg.next);\n\n// ***************\n// * Show Status *\n// ***************\nnode.status({\n fill: \"grey\",\n shape: \"dot\",\n text: `R:${cfg.lamps[0]} A:${cfg.lamps[1]} G:${cfg.lamps[2]} Delay:${cfg.delay}ms`\n});\n\n// ***************\n// * Return 4 outputs *\n// ***************\nreturn [red, amber, green, delayMsg];\n","outputs":4,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":760,"y":160,"wires":[["93814d1a6470edbc"],["db12c168fa131df2"],["a162a116a95762d3"],["36dd8a118669a23f"]]},{"id":"36dd8a118669a23f","type":"link out","z":"b5a1333e3bb6b1d0","name":"OUT_msg_delay","mode":"link","links":["d7970e785518ca56"],"x":915,"y":240,"wires":[]},{"id":"d7970e785518ca56","type":"link in","z":"b5a1333e3bb6b1d0","name":"IN_msg_delay","links":["36dd8a118669a23f"],"x":265,"y":240,"wires":[["958e1a7760c9bf69"]]},{"id":"6cc0d48304b8068c","type":"comment","z":"b5a1333e3bb6b1d0","name":"FSM-v2 with enum types for 'STATES' and 'STATE_TABLE'","info":"","x":630,"y":240,"wires":[]}]
Please note the above FSM is a Deterministic Finite State Machine (DFSM) or Linear FSM or Sequential FSM. If you need a 'condition' to be used to determine which state the machine goes to next, then it needs to be coded as a 'Mealy Machine' like the 'Door Lock System' above.