Homer
Published © Apache-2.0

Graphical Programming for Your Own IoT Board

Wanna have Scratch-style programming for your IoT board? Let me introduce you Entry, an open-source software that you can easily customize.

BeginnerFull instructions provided3 hours748
Graphical Programming for Your Own IoT Board

Things used in this project

Hardware components

PHPoC Blue
PHPoC Blue
×1
Ultrasonic Sensor - HC-SR04 (Generic)
Ultrasonic Sensor - HC-SR04 (Generic)
×1

Software apps and online services

Entry
From their homepage: Entry is an education platform created to help anyone learn to code. Students are able to learn to code while playing. Teachers are able to teach and manage students effectively.
Node.js

Story

Read more

Code

block_phpoc.js

JavaScript
Declare hardware blocks and the functions to interface with PHPoC
/*

- Created by Homer(https://www.hackster.io/Homer)

*/

'use strict';

Entry.PHPoC = {
    name: 'phpoc',
    imageName: 'phpoc.png',
    title: {
        "ko": "PHPoC ๋ณด๋“œ",
        "en": "PHPoC Board"
    },
	deviceVersion: '99',
	deviceID: '24.1',
	isConnected: false,
    setZero: function() {
		let that = Entry.PHPoC;
		that.recentCommands = {};
        Entry.hw.update();
		let rstCmd = that.genCommand(that.commands.RST);
		that.sendWSdata(rstCmd);
    },
	commands: {
		POLL: 0,		
		RST: 1,
		GET: 2,
	    SET: 3
	},
    sensorTypes: {
        DIGITAL: 1,
        ANALOG: 2,
        SERVO_PIN: 3,
        ULTRASONIC: 4,
    },
	inputData: {
		DIGITAL: {
			'8': 1,
			'9': 1,
			'12': 1,
			'13': 1,
			'14': 1,
			'15': 1,
			'16': 1,
			'17': 1,
			'18': 1,
			'19': 1,
			'20': 1,
			'21': 1,
		},
		ANALOG: {
			'0': 0,
			'1': 0,
			'2': 0,
			'3': 0,
			'4': 0,
			'5': 0,
			'6': 0,
		},
		ULTRASONIC: 0,
	},
	readablePorts: [],
	recentCommands: {},
	
	toogleBlockView: function(isShown){
		let that = Entry.PHPoC;
		let hw = Entry.hw;
		if (isShown){
			hw.selectedDevice = that.deviceID;
			hw.hwModule = hw.hwInfo[Entry.PHPoC.deviceID];
			that.showBlocks();
		}
		else {
			Entry.propertyPanel && Entry.propertyPanel.removeMode("hw");
			hw.selectedDevice = undefined;
			hw.hwModule = undefined;
			Entry.dispatchEvent("hwChanged");
		}		
	},
	showBlocks: function () {
        var self = Entry.playground;

        var WS = self.mainWorkspace;
        if (!WS) return;
        var blockMenu = WS.blockMenu;
        if (!blockMenu) return;

        var hw = Entry.hw;
        if (hw) {
            hw.banHW();
            if (hw.hwModule) {
                blockMenu.unbanClass(hw.hwModule.name);
            }
        } else {
            blockMenu.banClass("arduinoConnected", true);
            blockMenu.banClass("arduinoConnect", true);
            blockMenu.unbanClass("arduinoDisconnected", true);
            Entry.hw.banHW();
        }

        blockMenu.hwCodeOutdated = true;
        blockMenu._generateHwCode(true);
        blockMenu.reDraw();
    },
	
	webSocketClient: null,

	initWS: function(url){
		let that = Entry.PHPoC;
		if(!that.webSocketClient){
			that.webSocketClient = new WebSocket('ws://'+url+'/entry', 'text.phpoc');
			console.log(that.webSocketClient);
			that.webSocketClient.onerror = that.ws_onerror;
			that.webSocketClient.onopen = that.ws_onopen;
			that.webSocketClient.onclose = that.ws_onclose;
			that.webSocketClient.onmessage = that.ws_onmessage;
		}
	},
	
	closeWS: function(){
		let that = Entry.PHPoC;
		let hw = Entry.hw;	
		that.webSocketClient = null;
		that.clearPolling();
		that.recentCommands = {};
		Entry.propertyPanel && Entry.propertyPanel.removeMode("hw");
		hw.selectedDevice = undefined;
		hw.hwModule = undefined;
		Entry.dispatchEvent("hwChanged");
		if(that.isConnected){
			Entry.toast.warning(Lang.Msgs.warn, 'PHPoC WebSocket disconnected');
			that.isConnected = false;
		}
	},

	ws_onopen: function() {
		let that = Entry.PHPoC;
		let hw = Entry.hw;
		console.log('WebSocket Client Connected');
		that.isConnected = true;
		hw.connected = true;
		that.toogleBlockView(true);
		Entry.dispatchEvent("hwChanged");
		let descMsg = Lang.Msgs.hw_connection_success_desc2;
		Entry.toast.success(Lang.Msgs.hw_connection_success, descMsg);

		if (Entry.playground && Entry.playground.object) {
			Entry.playground.setMenu(Entry.playground.object.objectType);
		}
		Entry.PHPoC.sendPolling();				
	},
	sendWSdata: function(dt){
		let that = Entry.PHPoC;
		if (that.isConnected){
			that.webSocketClient.send(dt);
			console.log(dt);
		}			
	},
	ws_onerror: function(){
		console.log('WebSocket Connection Error');
		Entry.PHPoC.closeWS();
	},	
	ws_onclose: function() {
		console.log('WebSocket Client Closed');
		let that = Entry.PHPoC;
		Entry.PHPoC.closeWS();
	},

	ws_onmessage: function(msg) {
		let that = Entry.PHPoC;
		if (typeof msg.data === 'string') {
			let recvData = msg.data.split("\n");
			recvData.forEach(function(dt){
			let fields = dt.split("/");
			let c = parseInt(fields[0]);
			let t = parseInt(fields[1]);
			let p = fields[2];
			let v = parseInt(fields[3]);
			if (c == that.commands.GET){
				switch(t){
					case (that.sensorTypes.ANALOG):
						that.inputData.ANALOG[p] = v;
						break;
					case (that.sensorTypes.DIGITAL):
						Entry.PHPoC.inputData.DIGITAL[p] = v;
						break;
					case (that.sensorTypes.ULTRASONIC):
						that.inputData.ULTRASONIC = parseFloat(p).toFixed(2);
						break;
					}
			}
			});	
		}
	},
	
	pollingFunc: null,
	sendPolling: function(){	
		if(!Entry.PHPoC.pollingFunc){
			let pollCmd = Entry.PHPoC.genCommand(Entry.PHPoC.commands.POLL);
			Entry.PHPoC.pollingFunc = setInterval(function(){
				Entry.PHPoC.sendWSdata(pollCmd);
			}, 500);
		}
	},
	clearPolling: function(){
		clearInterval(this.pollingFunc);
		Entry.PHPoC.pollingFunc = null;
	},
	
	
	sendCommand: function(obj){
		let that = Entry.PHPoC;
		if (obj){						
			if (obj.cmd === that.commands.GET){
				if (!that.recentCommands['GET']){
					that.recentCommands['GET'] = {};
				}	
				if (
					typeof obj.port === 'string' ||
					typeof obj.port === 'number'
				) {
					if ((obj.type !== that.recentCommands.GET.type)||
						(obj.port !== that.recentCommands.GET.port)) {	
							that.recentCommands.GET = obj;						
							that.sendWSdata(that.genCommand(obj.cmd, obj.type, obj.port));
						}
				}
				else if (Array.isArray(obj.port)) {
						
					if ((obj.type !== that.recentCommands.GET.type)||
						(obj.port[0] !== that.recentCommands.GET.port[0])||
						(obj.port[1] !== that.recentCommands.GET.port[1])) {	
							that.recentCommands.GET = obj;						
							that.sendWSdata(that.genCommand(obj.cmd, obj.type, obj.port[0], obj.port[1]));
					}
				}
			}
			else if (obj.cmd === that.commands.SET) {
				if (!that.recentCommands['SET']){
					that.recentCommands['SET'] = {};
				}
				if (
					typeof obj.port === 'string' ||
					typeof obj.port === 'number'
				) {
					if ((obj.type !== that.recentCommands.SET.type)||
						(obj.data !== that.recentCommands.SET.data)||
						(obj.port !== that.recentCommands.SET.port)) {	
							that.recentCommands.SET = obj;						
							that.sendWSdata(that.genCommand(obj.cmd, obj.type, obj.port, obj.data));
						}
				}
				else if (Array.isArray(obj.port)) {
					if ((obj.type !== that.recentCommands.SET.type)||
						(obj.port[0] !== that.recentCommands.SET.port[0])||
						(obj.port[1] !== that.recentCommands.SET.port[1])) {	
							that.recentCommands.SET = obj;						
							that.sendWSdata(that.genCommand(obj.cmd, obj.type, obj.port[0], obj.port[1]));
					}
				}					
			}								
		}
	},
	
	genCommand: function(cmd, type, port, value){
		let str = cmd;
		if (type!=null)
			str += '/' + type;
		if (port!=null)
			str += '/' + port;
		if (value!=null)
			str += '/' + value;
		return (str + '\n');
	},

		
};

Entry.PHPoC.setLanguage = function() {
    return {
        ko: {
            template: {
				phpoc_connect: 'WebSocket์— ์—ฐ๊ฒฐ๋จ %1',
                phpoc_get_analog_value: '์•„๋‚ ๋กœ๊ทธ %1 ๋ฒˆ ์„ผ์„œ๊ฐ’',
                phpoc_value_map: '%1 ์˜ ๋ฒ”์œ„๋ฅผ %2 ~ %3 ์—์„œ %4 ~ %5 ๋กœ ๋ฐ”๊พผ๊ฐ’',
                phpoc_get_ultrasonic_value:'์šธํŠธ๋ผ์†Œ๋‹‰ Trig %1 Echo %2 ์„ผ์„œ๊ฐ’',
				phpoc_get_digital: '๋””์ง€ํ„ธ %1 ๋ฒˆ ์„ผ์„œ๊ฐ’',
				
                phpoc_set_digital: '๋””์ง€ํ„ธ %1 ๋ฒˆ %2 %3',
                phpoc_set_servo: 'ํ•€ %1 ๋ฒˆ ํ•€์˜ ์„œ๋ณด๋ชจํ„ฐ๋ฅผ %2 ์˜ ๊ฐ๋„๋กœ ์ •ํ•˜๊ธฐ %3',                
				phpoc_set_led: 'LED %1 ๋ฒˆ %2 %3',
				phpoc_disconnect: 'Stop WebSocket connection %1',
            }
        },
        en: {
            template: {
				phpoc_connect: 'Connected to Websocket %1',
                phpoc_get_analog_value: 'Value of Analog port %1',
                phpoc_value_map: 'Map %1 from %2 ~ %3 to %4 ~ %5',
                phpoc_get_ultrasonic_value: 'Read ultrasonic sensor Trig pin %1 Echo pin %2',               
                phpoc_get_digital: 'Input value of Digital port %1',
				
				phpoc_set_digital: 'Set digital port %1 output as %2 %3',
                phpoc_set_servo: 'Set servo pin %1 angle as %2 %3',
				phpoc_set_led: 'Set onboard LED %1 output %2 %3',
				phpoc_disconnect: 'Stop WebSocket connection %1',				
            }
        },
    };  
};


Entry.PHPoC.getBlocks = function() {
    return {
        //region PHPoC
		
		phpoc_show_block: {
			skeleton: 'basic_button',
			color: '#eee',
			isNotFor: ['arduinoDisconnected','arduinoConnect', 'arduinoConnected'],
			params: [{
				type: 'Text',
				text: Lang.Blocks.PHPOC_toggle,//'Toggle PHPoC Blocks',//Lang.Blocks.ARDUINO_reconnect,
				color: '#333',
				align: 'center'
			}],
			events: {
				mousedown: [function () {
					//Entry.hw.retryConnect();
					if (!Entry.hw.selectedDevice){
						Entry.PHPoC.toogleBlockView(true);
					}
					else if (Entry.hw.selectedDevice===Entry.PHPoC.deviceID){
						Entry.PHPoC.toogleBlockView(false);
					}
				}]
			}
		},			
        phpoc_analog_list: {
            color: '#00979D',
            skeleton: 'basic_string_field',
            statements: [],
            template: '%1',
            params: [
                {
                    type: 'Dropdown',
                    options: [
                        ['A0', '0'],
                        ['A1', '1'],
                        ['A2', '2'],
                        ['A3', '3'],
                        ['A4', '4'],
                        ['A5', '5'],
                    ],
                    value: '0',
                    fontSize: 11,
                },
            ],
            events: {},
            def: {
                params: [null],
            },
            paramsKeyMap: {
                PORT: 0,
            },
            func: function(sprite, script) {
                return script.getField('PORT');
            },
            syntax: { js: [], py: [] },
        },
		
		phpoc_digital_list: {
            color: '#00979D',
            skeleton: 'basic_string_field',
            statements: [],
            template: '%1',
            params: [
                {
                    type: 'Dropdown',
                    options: [
						['8', '8'],
						['9', '9'],
                        ['12', '12'],
                        ['13', '13'],
                        ['14', '14'],
                        ['15', '15'],
                        ['16', '16'],
                        ['17', '17'],
						['18', '18'],
						['19', '19'],
						['20', '20'],
						['21', '21'],						
                    ],
                    value: '0',
                    fontSize: 11,
                },
            ],
            events: {},
            def: {
                params: [null],
            },
            paramsKeyMap: {
                PORT: 0,
            },
            func: function(sprite, script) {
                return script.getField('PORT');
            },
            syntax: { js: [], py: [] },
        },		
		phpoc_ht_list: {
            color: '#00979D',
            skeleton: 'basic_string_field',
            statements: [],
            template: '%1',
            params: [
                {
                    type: 'Dropdown',
                    options: [
						['HT0', 'HT0'],
						['HT1', 'HT1'],
                        ['HT2', 'HT2'],
                        ['HT3', 'HT3'],
                    ],
                    value: 'HT0',
                    fontSize: 11,
                },
            ],
            events: {},
            def: {
                params: [null],
            },
            paramsKeyMap: {
                PORT: 0,
            },
            func: function(sprite, script) {
                return script.getField('PORT');
            },
            syntax: { js: [], py: [] },
        },
		phpoc_get_digital: {
            color: '#00979D',
            fontColor: '#fff',
            skeleton: 'basic_boolean_field',
            params: [
                {
                    type: 'Block',
                    accept: 'string',
                },
            ],
            events: {},
            def: {
                params: [
                    {
                        type: 'phpoc_digital_list',
                        params: ['8'],
                    },
                ],
                type: 'phpoc_get_digital',
            },
            paramsKeyMap: {
                PORT: 0,
            },
            class: 'PHPoCGet',
            isNotFor: ['phpoc'],
            func: function(sprite, script) {
                let port = script.getNumberValue('PORT', script);
				if (Entry.PHPoC.readablePorts.indexOf(port) == -1){					
					let obj_get = {
						type: Entry.PHPoC.sensorTypes.DIGITAL,
						cmd: Entry.PHPoC.commands.GET,
						port: port
					};					
					Entry.PHPoC.sendCommand(obj_get);
					Entry.PHPoC.readablePorts.push(port);
				}
                let DIGITAL = Entry.PHPoC.inputData.DIGITAL;
                return DIGITAL ? DIGITAL[port] || 0 : 0;
            },
            syntax: { js: [], py: [] },
        },	
        phpoc_get_analog_value: {
            color: '#00979D',
            fontColor: '#fff',
            skeleton: 'basic_string_field',
            statements: [],
            params: [
                {
                    type: 'Block',
                    accept: 'string',
                },
            ],
            events: {},
            def: {
                params: [
                    {
                        type: 'phpoc_analog_list',
                    },
                ],
                type: 'phpoc_get_analog_value',
            },
            paramsKeyMap: {
                PORT: 0,
            },
            class: 'PHPoCGet',
            isNotFor: ['phpoc'],
            func: function(sprite, script) {
                let port = script.getValue('PORT', script);
                let ANALOG = Entry.PHPoC.inputData.ANALOG;
                return ANALOG ? ANALOG[port] || 0 : 0;
            },
            syntax: { js: [], py: [] },
        },
        phpoc_value_map: {
            color: '#00979D',
            fontColor: '#fff',
            skeleton: 'basic_string_field',
            statements: [],
            params: [
                {
                    type: 'Block',
                    accept: 'string',
                },
                {
                    type: 'Block',
                    accept: 'string',
                },
                {
                    type: 'Block',
                    accept: 'string',
                },
                {
                    type: 'Block',
                    accept: 'string',
                },
                {
                    type: 'Block',
                    accept: 'string',
                },
            ],
            events: {},
            def: {
                params: [
                    {
                        type: 'number',
                        params: ['20'],
                    },
                    {
                        type: 'number',
                        params: ['0'],
                    },
                    {
                        type: 'number',
                        params: ['4095'],
                    },
                    {
                        type: 'number',
                        params: ['0'],
                    },
                    {
                        type: 'number',
                        params: ['100'],
                    },
                ],
                type: 'phpoc_value_map',
            },
            paramsKeyMap: {
                PORT: 0,
                VALUE2: 1,
                VALUE3: 2,
                VALUE4: 3,
                VALUE5: 4,
            },
            class: 'PHPoCGet',
            isNotFor: ['phpoc'],
            func: function(sprite, script) {
                let result = script.getValue('PORT', script);
                let value2 = script.getNumberValue('VALUE2', script);
                let value3 = script.getNumberValue('VALUE3', script);
                let value4 = script.getNumberValue('VALUE4', script);
                let value5 = script.getNumberValue('VALUE5', script);
                let stringValue4 = script.getValue('VALUE4', script);
                let stringValue5 = script.getValue('VALUE5', script);
                let isFloat = false;

                if (
                    (Entry.Utils.isNumber(stringValue4) &&
                        stringValue4.indexOf('.') > -1) ||
                    (Entry.Utils.isNumber(stringValue5) &&
                        stringValue5.indexOf('.') > -1)
                ) {
                    isFloat = true;
                }

                if (value2 > value3) {
                    let swap = value2;
                    value2 = value3;
                    value3 = swap;
                }
                if (value4 > value5) {
                    let swap = value4;
                    value4 = value5;
                    value5 = swap;
                }
                result -= value2;
                result = result * ((value5 - value4) / (value3 - value2));
                result += value4;
                result = Math.min(value5, result);
                result = Math.max(value4, result);

                if (isFloat) {
                    result = Math.round(result * 100) / 100;
                } else {
                    result = Math.round(result);
                }

                return result;
            },
            syntax: { js: [], py: [] },
        },
        phpoc_get_ultrasonic_value: {
            color: '#00979D',
            fontColor: '#fff',
            skeleton: 'basic_string_field',
            statements: [],
            params: [
                {
                    type: 'Block',
                    accept: 'string',
                },
                {
                    type: 'Block',
                    accept: 'string',
                },
            ],
            events: {},
            def: {
                params: [
                    {
                        type: 'phpoc_ht_list',
                        params: ['HT2'],
                    },
                    {
                        type: 'phpoc_ht_list',
                        params: ['HT3'],
                    },
                ],
                type: 'phpoc_get_ultrasonic_value',
            },
            paramsKeyMap: {
                PORT1: 0,
                PORT2: 1,
            },
            class: 'PHPoCGet',
            isNotFor: ['phpoc'],
            func: function(sprite, script) {
							
                let port1 = script.getValue('PORT1', script);
                let port2 = script.getValue('PORT2', script);
	

				
			    let obj_set = {
                    type: Entry.PHPoC.sensorTypes.ULTRASONIC,
                    cmd: Entry.PHPoC.commands.SET,
					port: [port1, port2],
                };

				Entry.PHPoC.sendCommand(obj_set);
				
				let obj_get = {
                    type: Entry.PHPoC.sensorTypes.ULTRASONIC,
                    cmd: Entry.PHPoC.commands.GET,
					port: [port1, port2],
                };
				Entry.PHPoC.sendCommand(obj_get);									
                return Entry.PHPoC.inputData.ULTRASONIC || 0;
            },
            syntax: { js: [], py: [] },
        },
        phpoc_set_digital: {
            color: '#00979D',
            skeleton: 'basic',
            statements: [],
            params: [
                {
                    type: 'Block',
                    accept: 'string',
                },
                {

                    type: 'Dropdown',
                    options: [
						['HIGH', '1'],
						['LOW', '0'],
                    ],
					value: '1',
                },
                {
                    type: 'Indicator',
                    img: 'block_icon/hardware_03.png',
                    size: 12,
                },
            ],
            events: {},
            def: {
                params: [
                    {
                        type: 'phpoc_digital_list',
                        params: ['9'],
                    },
					null,
					null,
				
                ],
                type: 'phpoc_set_digital',
            },
            paramsKeyMap: {
                PORT: 0,
                VALUE: 1,
            },
            class: 'PHPoCSet',
            isNotFor: ['phpoc'],
            func: function(sprite, script) {				
                let port = script.getNumberValue('PORT', script);
				let value = script.getField('VALUE');
				let index = Entry.PHPoC.readablePorts.indexOf(port);
				if (index > -1){	
					Entry.PHPoC.readablePorts.splice(index, 1);
				}
				let obj_set = {
					type: Entry.PHPoC.sensorTypes.DIGITAL,
					data: value,
					cmd: Entry.PHPoC.commands.SET,
					port: port
				};
				Entry.PHPoC.sendCommand(obj_set);
                return script.callReturn();
            },
            syntax: { js: [], py: [] },
        },
		phpoc_set_led: {
            color: '#00979D',
            skeleton: 'basic',
            statements: [],
            params: [
                {
                    type: 'Dropdown',
                    options: [
						['1', '30'],
						['2', '31'],
                    ],
					value: '30',
                },
                {

                    type: 'Dropdown',
                    options: [
						['OFF', '1'],
						['ON', '0'],
                    ],
					value: '1',
                },
                {
                    type: 'Indicator',
                    img: 'block_icon/hardware_03.png',
                    size: 12,
                },
            ],
            events: {},
            def: {
                params: [
                    null,
					null,
					null,
                ],
                type: 'phpoc_set_led',
            },
            paramsKeyMap: {
                PORT: 0,
                VALUE: 1,
            },
            class: 'PHPoCSet',
            isNotFor: ['phpoc'],
            func: function(sprite, script) {
                let port = script.getField('PORT');
				let value = script.getField('VALUE');				

                let obj_set = {
                    type: Entry.PHPoC.sensorTypes.DIGITAL,
                    data: value,
                    cmd: Entry.PHPoC.commands.SET,
					port: port
                };
				Entry.PHPoC.sendCommand(obj_set);
				
                return script.callReturn();
            },
            syntax: { js: [], py: [] },
        },
        phpoc_set_servo: {
            color: '#00979D',
            skeleton: 'basic',
            statements: [],
            params: [
                {
                    type: 'Block',
                    accept: 'string',
                },
                {
                    type: 'Block',
                    accept: 'string',
                },
				{
                    type: 'Indicator',
                    img: 'block_icon/hardware_03.png',
                    size: 12,
                },
            ],
            events: {},
            def: {
                params: [
                    {
                        type: 'phpoc_ht_list',
                    },
					{
						type: "number",
						params: ['45']
					},
					null,
                ],
                type: 'phpoc_set_servo',
            },
            paramsKeyMap: {
                PORT: 0,
                VALUE: 1,
            },
            class: 'PHPoCSet',
            isNotFor: ['phpoc'],
            func: function(sprite, script) {
                let port = script.getValue('PORT', script);
                let value = script.getNumberValue('VALUE', script);
                value = Math.min(180, value);
                value = Math.max(0, value);


				let obt_set = {
                    type: Entry.PHPoC.sensorTypes.SERVO_PIN,
                    data: value,
                    cmd: Entry.PHPoC.commands.SET,
					port: port,
                };
				Entry.PHPoC.sendCommand(obt_set);
				
				
                return script.callReturn();
            },
            syntax: { js: [], py: [] },
        },	
		phpoc_connect: {
            color: '#00979D',
			fontColor: '#fff',
			skeleton: 'basic_boolean_field',
            statements: [],
            params: [
                {
                    type: 'Block',
                    accept: 'string',
					value: '0.0.0.0',
                },
            ],
            events: {},
            def: {
                params: [
					null,
					//null,
                ],
                type: 'phpoc_connect',
            },
            paramsKeyMap: {
                ADDR: 0,
            },
            class: 'PHPoCGet',
			isNotFor: ['phpoc'],
            func: function(sprite, script) {			
                let url = script.getStringValue('ADDR', script);
				Entry.PHPoC.initWS(url);		
                return Entry.PHPoC.isConnected;//script.callReturn();
            },
            syntax: { js: [], py: [] },
        },
		phpoc_disconnect: {
            color: '#00979D',
			class: 'PHPoCSet',
			skeleton: 'basic',
            statements: [],
            params: [
                {
                    type: 'Indicator',
                    img: 'block_icon/hardware_03.png',
                    size: 12,
                },
            ],
            events: {},
            def: {
                params: [
					null,
                ],
                type: 'phpoc_disconnect',
            },
            paramsKeyMap: {
                ADDR: 0,
            },
			isNotFor: ['phpoc'],
            func: function(sprite, script) {
				if (Entry.PHPoC.webSocketClient)
					Entry.PHPoC.webSocketClient.close();
				
                return script.callReturn();
            },
            syntax: { js: [], py: [] },
        },		
        //endregion PHPoC
    };
}

task0.php

PHP
This file needs to be loaded and run on PHPoC device.
<?php
if(_SERVER("REQUEST_METHOD"))
    exit; // avoid php execution via http request

include_once "/lib/sd_340.php";
include_once "/lib/sn_tcp_ws.php";

define("WS_ID", 1);
define("WS_PATH", "entry");

define("POLL", "0");
define("RST", "1");
define("GET", "2");
define("SET", "3");

// Define peripheral types
define("DIGITAL", "1");
define("ANALOG", "2");
define("SERVO", "3");
define("ULTRASONIC", "4");

define("PWM_PERIOD", 20000); 
define("WIDTH_MIN", 771);
define("WIDTH_MAX", 2193);

$uio_list = array(8, 9, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21);

function init_device(){
	global $uio_list;
	ht_pwm_setup(0, 0, PWM_PERIOD, "us");
	ht_pwm_setup(1, 0, PWM_PERIOD, "us");
	ht_pwm_setup(2, 0, PWM_PERIOD, "us");
	ht_pwm_setup(3, 0, PWM_PERIOD, "us");
	
	for($i=0; $i<12; $i++){
    	uio_setup(0, $uio_list[$i], "in_pu"); 
	}
	uio_setup(0, 30, "out high");
	uio_setup(0, 31, "out high");
}

function set_ultrasonic_trig($pin){
	ht_ioctl($pin, "reset");
	ht_ioctl($pin, "set div us");
	ht_ioctl($pin, "set mode output pulse");
	ht_ioctl($pin, "set repc 1");
	ht_ioctl($pin, "set count 5 10"); 
}

function set_ultrasonic_echo($pin){
	ht_ioctl($pin, "reset");
	ht_ioctl($pin, "set div us");
	ht_ioctl($pin, "set mode capture toggle");
	ht_ioctl($pin, "set trigger from pin rise");
	ht_ioctl($pin, "set repc 4");
}

function get_ht_pin($pin){
	switch($pin){
		case "HT0":
			return 0;
		case "HT1":
			return 1;
		case "HT2":
			return 2;
		case "HT3":
			return 3;
		default:
			return -1;
	}
}

function get_ultrasonic_value($echo_pin, $trig_pin){
	ht_ioctl($echo_pin, "start"); 
	ht_ioctl($trig_pin, "start"); 
 
	usleep(100000); 
	ht_ioctl($trig_pin, "stop");
 
	$us = ht_ioctl($echo_pin, "get count 1");
	$dist = $us * 340.0 / 2;
	$dist = $dist / 10000;
	return $dist;
}

function servo_set_angle($id, $angle) 
{             
    $width = WIDTH_MIN + (int)round((WIDTH_MAX - WIDTH_MIN) * $angle / 180.0);
	if(($width >= WIDTH_MIN) && ($width <= WIDTH_MAX))
        ht_pwm_width($id, $width, PWM_PERIOD);
}

init_device();
$use_ultrasonic = FALSE;
ws_setup(WS_ID, WS_PATH, "text.phpoc");

$rwbuf = "";
while(1)
{
	if(ws_state(WS_ID) == TCP_CONNECTED)
	{
		$rlen = ws_read(WS_ID, $rwbuf);
		if($rlen)
		{
			$cmd_list = explode("\n",$rwbuf);
            $len = count($cmd_list)-1;
			$time_out=0;
            for ($idx = 0; $idx<$len; $idx++){
				$ret = "";		
				echo $cmd_list[$idx], "\r\n";
                $cmd = explode("/",$cmd_list[$idx]);
                switch($cmd[0]){
                    case SET:
                    	switch($cmd[1]){
	                    	case DIGITAL:
								$pin = (int)$cmd[2];
								uio_setup(0, $pin, "out high");
								if ($cmd[3] == "0")
									uio_out(0, $pin, LOW);			
								else
									uio_out(0, $pin, HIGH);
								break;
							case SERVO:
								$pin = get_ht_pin($cmd[2]);
								if ($pin>-1){
									servo_set_angle($pin, (int)$cmd[3]);
								}
								break;
							case ULTRASONIC:
								$trig_pin = get_ht_pin($cmd[2]);
								$echo_pin = get_ht_pin($cmd[3]);
								set_ultrasonic_trig($trig_pin);
								set_ultrasonic_echo($echo_pin);
								break;
						}
						break;
					case GET:
						switch($cmd[1]){
							case DIGITAL:
								uio_setup(0, (int)$cmd[2], "in_pu"); 
								break;
							case ULTRASONIC:
								$trig_pin = get_ht_pin($cmd[2]);
								$echo_pin =  get_ht_pin($cmd[3]);
								if (($trig_pin>-1)&&($echo_pin>-1)){
									$use_ultrasonic = TRUE;
								}
								break;
							}
						break;
                    case RST:
                        init_device();                     
                        $use_ultrasonic = FALSE;
                        break;
                    case POLL:							
                        for($i=0; $i<12;$i++){
						    $pin = $uio_list[$i];
							$d_in = uio_in(0, $pin);
							$ret = $ret.GET."/".DIGITAL."/".(string)$pin."/".(string)$d_in."\n";
						}
						if ($use_ultrasonic){
							$dist = get_ultrasonic_value($echo_pin, $trig_pin);
							$ret = $ret.GET."/".ULTRASONIC."/".(string)$dist."\n";	
						}
						for($pin=0; $pin<=5;$pin++){
							adc_setup(0, $pin);
							$adc_in = adc_in(0, 30);
							$ret = $ret.GET."/".ANALOG."/".(string)$pin."/".(string)$adc_in."\n";
						}
						ws_write(WS_ID, $ret); 
                        break;
                              }
            }	
		}
	}
}
?>

Credits

Homer

Homer

17 projects โ€ข 32 followers

Comments