Hackster is hosting Hackster Holidays, Ep. 7: Livestream & Giveaway Drawing. Watch previous episodes or stream live on Friday!Stream Hackster Holidays, Ep. 7 on Friday!

Mobius_Int. Developer Competition

Smart pet helper for a healthy society with busy modern people and pets.

IntermediateFull instructions provided10 hours247
Mobius_Int. Developer Competition

Things used in this project

Hardware components

Raspberry Pi 4 Model B
Raspberry Pi 4 Model B
To communicate with the server, it's installed in a feeding device, training device, harness.
×2
Arduino UNO
Arduino UNO
To control servo motor.
×1
servo motor
To auto feeding. and training.
×6
web cam
take a photo for capture dog and cctv function.
×2
gps
To detect pet's location
×1
Ultrisonic sensor
Sensor to check the remaining amount of feed and whether they are eating.
×2

Story

Read more

Schematics

Flow chart

The overall flow chart.

Detail chart

Detailed description between servers, applications, and IoT edge devices.
(include detailed function)

Code

motion package streaming service

SH
Provides streaming service using motion package
sudo apt-get install motion

Image classification model

Python
Make dog sit / stand image classifier by using Resnet50
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras.applications import ResNet50
import pandas as pd
import numpy as np
from tensorflow.keras.preprocessing.image import ImageDataGenerator

train_datagen = ImageDataGenerator(rescale = 1./255,
                                   width_shift_range=0.2,
                                   shear_range = 0.2,
                                   zoom_range = 0.2,
                                   horizontal_flip = True
                                  )
test_datagen = ImageDataGenerator(rescale = 1./255)

training_set = train_datagen.flow_from_directory('C:/Users/hjhhi\OneDrive - sch.ac.kr\LectureCode\mobius\downloads',
                                                 target_size = (200, 200),
                                                 class_mode = 'binary')

test_set = test_datagen.flow_from_directory('C:/Users\hjhhi\OneDrive - sch.ac.kr\LectureCode\mobius/test',
                                            target_size = (200, 200),
                                            class_mode = 'binary')

model = tf.keras.models.Sequential()
model.add(ResNet50(include_top=True, weights=None, input_shape=(200, 200, 3), classes=2))

model.summary()

model.compile(
    optimizer='adam',
    loss='sparse_categorical_crossentropy', 
    metrics=['accuracy'],
)

history = model.fit_generator(training_set, epochs=100, validation_data=test_set)

model.save('model_last_1.h5')

model = tf.keras.models.load_model('model_last_1.h5')

converter = tf.lite.TFLiteConverter.from_keras_model(model)

tflite_model = converter.convert()

### Test code before export Raspberrypi 

#open("model.tflite","wb").write(tflite_model)

#last_set = test_datagen.flow_from_directory('C:/Users/hjhhi\OneDrive - sch.ac.kr\LectureCode\mobius\instance',
#                                                 target_size = (200, 200),
#                                                  batch_size = 32,
#                                                 class_mode = 'binary')

##percentage for class will printed
## sit = 0, standing = 1
#model.predict_generator(last_set)

Raspberrypi dog train classfier

Python
Takes picture of dog while training.
It can print percentage of dog is sitting or standing.
import requests
import tensorflow as tf
import os
import sys
import numpy as np
from tensorflow.keras.preprocessing.image import ImageDataGenerator


test_datagen = ImageDataGenerator(rescale = 1./255)

os.system('fswebcam ./sample/instance/image.jpg')
test_set = test_datagen.flow_from_directory('./sample',
                                            target_size = (200, 200),
#                                             batch_size = 32,
                                            class_mode = 'binary')



interpreter = tf.lite.Interpreter(model_path="model.tflite")
interpreter.allocate_tensors()
input_details = interpreter.get_input_details()
output_details = interpreter.get_output_details()
input_image = test_set



#X_train, y_train = next(input_image)
X_train = np.asarray(input_image[0][0])



X_train.shape



interpreter.set_tensor(input_details[0]['index'], X_train)
interpreter.invoke()



output_data = interpreter.get_tensor(output_details[0]['index'])
output = np.argmax(output_data)

return_value = output == 1
mobius_data = int(return_value)


url = 'http://203.253.128.177:7579/Mobius/walwal/success'
headers =	{
				'Accept':'application/json',
				'X-M2M-RI':'12345',
				'X-M2M-Origin':'XXXXXXXXXXX', # change to your aei
				'Content-Type':'application/vnd.onem2m-res+json; ty=4'
			}

data =	{
			"m2m:cin": {
				"con": mobius_data
			}
		}

r = requests.post(url, headers=headers, json=data)

print("END OF SIT")

try:
	r.raise_for_status()
	print(r)
except Exception as exc:
	print('There was a problem: %s' % (exc))

Raspberrypi dog train classfier_2

Python
Takes picture of dog while training.
It can print percentage of dog is wating or moving.
import tensorflow as tf
import numpy as np
from tensorflow.keras.preprocessing.image import ImageDataGenerator
import pandas as pd
import requests
import time
import os

test_datagen = ImageDataGenerator(rescale = 1./255)

os.system('fswebcam ./sample2/instance/image_1.jpg')
time.sleep(3)
os.system('fswebcam ./sample2/instance/image_2.jpg')


test_set = test_datagen.flow_from_directory('./sample2',
                                            target_size = (200, 200),
#                                             batch_size = 32,
                                            class_mode = 'binary')
input_image = test_set


X_train = np.asarray(input_image[0][0])

count=0
for i in (X_train[0]*0.9 <=  X_train[1]) & (X_train[1] <=  X_train[0]*1.1):
    j = pd.DataFrame(i)
    if (len(j[j[0].values == True])) < 150:
        count = count+1

return_value = count > 100
mobius_data = int(return_value)
print("END OF WAIT")

print("END OF WAIT")


url = 'http://203.253.128.177:7579/Mobius/walwal/success'
headers =	{
				'Accept':'application/json',
				'X-M2M-RI':'12345',
				'X-M2M-Origin':'XXXXXXXXXXX', # change to your aei
				'Content-Type':'application/vnd.onem2m-res+json; ty=4'
			}

data =	{
			"m2m:cin": {
				"con": mobius_data
			}
		}

r = requests.post(url, headers=headers, json=data)

try:
	r.raise_for_status()
	print(r)
except Exception as exc:
	print('There was a problem: %s' % (exc))

Dog feed machine.

Python
A servo motor and a datetime module are used to allow dog food to come out at a specific time.
import RPi.GPIO as GPIO
import time
import datetime as dt

GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)

SERVO_PIN = 16
GPIO.setup(SERVO_PIN, GPIO.OUT)
servo = GPIO.PWM(SERVO_PIN, 50)

servo.start(0)


try:
	while True:
		now = dt.datetime.now()
		now_hour = now.hour
		now_min = now.minute
		print(now)
		if( now_hour == 8 and now_min == 00)or(now_hour == 20 and now_min == 00):
			servo.ChangeDutyCycle(7.5)
			time.sleep(4)
			servo.ChangeDutyCycle(12.5)
			time.sleep(57)
			print("Feeding Now!!!")
except KeyboardInterrupt:
	servo.stop( )
	GPIO.cleanup( )

Ultrasonic sensor dog food remaining amount of TAS app.js code.

JavaScript
Ultrasonic sensor dog food remaining amount of TAS code.
var net = require('net');
var util = require('util');
var fs = require('fs');
var xml2js = require('xml2js');

var wdt = require('./wdt');

var useparentport = '';
var useparenthostname = '';

var upload_arr = [];
var download_arr = [];

var conf = {};

// This is an async file read
fs.readFile('conf.xml', 'utf-8', function (err, data) {
    if (err) {
        console.log("FATAL An error occurred trying to read in the file: " + err);
        console.log("error : set to default for configuration")
    }
    else {
        var parser = new xml2js.Parser({explicitArray: false});
        parser.parseString(data, function (err, result) {
            if (err) {
                console.log("Parsing An error occurred trying to read in the file: " + err);
                console.log("error : set to default for configuration")
            }
            else {
                var jsonString = JSON.stringify(result);
                conf = JSON.parse(jsonString)['m2m:conf'];

                useparenthostname = conf.tas.parenthostname;
                useparentport = conf.tas.parentport;

                if (conf.upload != null) {
                    if (conf.upload['ctname'] != null) {
                        upload_arr[0] = conf.upload;
                    }
                    else {
                        upload_arr = conf.upload;
                    }
                }

                if (conf.download != null) {
                    if (conf.download['ctname'] != null) {
                        download_arr[0] = conf.download;
                    }
                    else {
                        download_arr = conf.download;
                    }
                }
            }
        });
    }
});

var tas_state = 'init';
var upload_client = null;
var t_count = 0;
var tas_download_count = 0;

function on_receive(data) {
    if (tas_state == 'connect' || tas_state == 'reconnect' || tas_state == 'upload') {
        var data_arr = data.toString().split('<EOF>');
        if (data_arr.length >= 2) {
            for (var i = 0; i < data_arr.length - 1; i++) {
                var line = data_arr[i];
                var sink_str = util.format('%s', line.toString());
                var sink_obj = JSON.parse(sink_str);

                if (sink_obj.ctname == null || sink_obj.con == null) {
                    console.log('Received: data format mismatch');
                }
                else {
                    if (sink_obj.con == 'hello') {
                        console.log('Received: ' + line);

                        if (++tas_download_count >= download_arr.length) {
                            tas_state = 'upload';
                        }
                    }
                    else {
                        for (var j = 0; j < upload_arr.length; j++) {
                            if (upload_arr[j].ctname == sink_obj.ctname) {
                                console.log('ACK : ' + line + ' <----');
                                break;
                            }
                        }

                        for (j = 0; j < download_arr.length; j++) {
                            if (download_arr[j].ctname == sink_obj.ctname) {
                                g_down_buf = JSON.stringify({id: download_arr[i].id, con: sink_obj.con});
                                console.log(g_down_buf + ' <----');
                                break;
                            }
                        }
                    }
                }
            }
        }
    }
}

function tas_watchdog() {
    if (tas_state == 'init') {
        upload_client = new net.Socket();

        upload_client.on('data', on_receive);

        upload_client.on('error', function(err) {
            console.log(err);
            tas_state = 'reconnect';
        });

        upload_client.on('close', function() {
            console.log('Connection closed');
            upload_client.destroy();
            tas_state = 'reconnect';
        });

        if (upload_client) {
            console.log('tas init ok');
            tas_state = 'init_thing';
        }
    }
    else if (tas_state == 'init_thing') {
        // init things

        tas_state = 'connect';
    }
    else if (tas_state == 'connect' || tas_state == 'reconnect') {
        upload_client.connect(useparentport, useparenthostname, function() {
            console.log('upload Connected');
            tas_download_count = 0;
            for (var i = 0; i < download_arr.length; i++) {
                console.log('download Connected - ' + download_arr[i].ctname + ' hello');
                var cin = {ctname: download_arr[i].ctname, con: 'hello'};
                upload_client.write(JSON.stringify(cin) + '<EOF>');
            }

            if (tas_download_count >= download_arr.length) {
                tas_state = 'upload';
            }
        });
    }
}

// Every 3 seconds, check if the TAS is not working
wdt.set_wdt(require('shortid').generate(), 3, tas_watchdog);

const Gpio = require('pigpio').Gpio;

// The number of microseconds it takes sound to travel 1cm at 20 degrees celcius
const MICROSECDONDS_PER_CM = 1e6/34321;

const trigger = new Gpio(20, {mode: Gpio.OUTPUT});          // GPIO20: trigger pin
const echo = new Gpio(21, {mode: Gpio.INPUT, alert: true}); // GPIO21: echo pin

const range_max = 600;  // maximum range for detection
const range_min = 0;  // minimum range for detection

var dist_0 = 0;
var dist_1 = 0;
var ultrasonic_update = true;

trigger.digitalWrite(0);

const watchHCSR04 = () => {
    let startTick;

    echo.on('alert', (level, tick) => {
        if (level == 1) {
            startTick = tick;
        } else {
            const endTick = tick;
            const diff = (endTick >> 0) - (startTick >> 0); // Unsigned 32 bit arithmetic
            // console.log(diff / 2 / MICROSECDONDS_PER_CM);
            dist_1 = (diff / 2 / MICROSECDONDS_PER_CM).toFixed(2);
            if (dist_1 >= range_max || dist_1 <= range_min)
                dist_1 =  -1;
        }
    });
};

watchHCSR04();

setInterval(() => {
    trigger.trigger(10, 1);
    if (ultrasonic_update) {
        if (tas_state=='upload') {
            for(var i = 0; i < upload_arr.length; i++) {
                Percent = Math.round(100-(dist_1/18*100))
                if(upload_arr[i].id != "ultrasound") {
                    var cin = {ctname: upload_arr[i].ctname, con: Percent};
                    console.log("SEND : " + JSON.stringify(cin) + ' ---->')
                    upload_client.write(JSON.stringify(cin) + '<EOF>');
                    break;
                }
            }
        }
        dist_0 = dist_1;
    }
}, 1000);

Ultrasonic sensor nCube conf.js code for remaining dog feed.

JavaScript
Ultrasonic sensor nCube conf.js code for remaining dog feed.
/**
 * Created by Il Yeup, Ahn in KETI on 2017-02-23.
 */

/**
 * Copyright (c) 2018, OCEAN
 * All rights reserved.
 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
 * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission.
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

var ip = require("ip");

var conf = {};
var cse = {};
var ae = {};
var cnt_arr = [];
var sub_arr = [];
var acp = {};

conf.useprotocol = 'http'; // select one for 'http' or 'mqtt' or 'coap' or 'ws'

// build cse
cse.host        = '203.253.128.177';
cse.port        = '7579';
cse.name        = 'Mobius';
cse.id          = '/Mobius2';
cse.mqttport    = '1883';
cse.wsport      = '7577';

// build ae
ae.name         = 'walwal';

ae.id           = 'SgkP2YGD89v';

ae.parent       = '/' + cse.name;
ae.appid        = 'measure_co2';
ae.port         = '9727';
ae.bodytype     = 'json'; // select 'json' or 'xml' or 'cbor'
ae.tasport      = '3105';

// build cnt
var count = 0;
cnt_arr[count] = {};
cnt_arr[count].parent = '/' + cse.name + '/' + ae.name;
cnt_arr[count++].name = 'remains';

// build sub
count = 0;
// --------
sub_arr[count] = {};
sub_arr[count].parent = '/' + cse.name + '/' + ae.name + '/' + cnt_arr[0].name;
sub_arr[count].name = 'sub';
sub_arr[count++].nu = 'mqtt://' + cse.host + '/' + ae.id + '?ct=' + ae.bodytype; // mqtt

// build acp: not complete
acp.parent = '/' + cse.name + '/' + ae.name;
acp.name = 'acp-' + ae.name;
acp.id = ae.id;

conf.usesecure  = 'disable';

if(conf.usesecure === 'enable') {
    cse.mqttport = '8883';
}

conf.cse = cse;
conf.ae = ae;
conf.cnt = cnt_arr;
conf.sub = sub_arr;
conf.acp = acp;


module.exports = conf;

Whether dogs eat food or not. TAS conf.xml code of ultrasonic sensor.

XML
Whether dogs eat food or not. TAS conf.xml code of ultrasonic sensor.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<m2m:conf xmlns:m2m="http://www.onem2m.org/xml/protocols" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <tas>
        <parenthostname>localhost</parenthostname>
        <parentport>3105</parentport>
    </tas>
    <upload>
        <ctname>eat</ctname>
        <id>eat#1</id>
    </upload>
</m2m:conf>

Whether dogs eat food or not. TAS app.js code of ultrasonic sensor.

JavaScript
Whether dogs eat food or not. TAS app.js code of ultrasonic sensor.
var net = require('net');
var util = require('util');
var fs = require('fs');
var xml2js = require('xml2js');

var wdt = require('./wdt');

var useparentport = '';
var useparenthostname = '';

var upload_arr = [];
var download_arr = [];

var conf = {};

// This is an async file read
fs.readFile('conf.xml', 'utf-8', function (err, data) {
    if (err) {
        console.log("FATAL An error occurred trying to read in the file: " + err);
        console.log("error : set to default for configuration")
    }
    else {
        var parser = new xml2js.Parser({explicitArray: false});
        parser.parseString(data, function (err, result) {
            if (err) {
                console.log("Parsing An error occurred trying to read in the file: " + err);
                console.log("error : set to default for configuration")
            }
            else {
                var jsonString = JSON.stringify(result);
                conf = JSON.parse(jsonString)['m2m:conf'];

                useparenthostname = conf.tas.parenthostname;
                useparentport = conf.tas.parentport;

                if (conf.upload != null) {
                    if (conf.upload['ctname'] != null) {
                        upload_arr[0] = conf.upload;
                    }
                    else {
                        upload_arr = conf.upload;
                    }
                }

                if (conf.download != null) {
                    if (conf.download['ctname'] != null) {
                        download_arr[0] = conf.download;
                    }
                    else {
                        download_arr = conf.download;
                    }
                }
            }
        });
    }
});

var tas_state = 'init';
var upload_client = null;
var t_count = 0;
var tas_download_count = 0;

function on_receive(data) {
    if (tas_state == 'connect' || tas_state == 'reconnect' || tas_state == 'upload') {
        var data_arr = data.toString().split('<EOF>');
        if (data_arr.length >= 2) {
            for (var i = 0; i < data_arr.length - 1; i++) {
                var line = data_arr[i];
                var sink_str = util.format('%s', line.toString());
                var sink_obj = JSON.parse(sink_str);

                if (sink_obj.ctname == null || sink_obj.con == null) {
                    console.log('Received: data format mismatch');
                }
                else {
                    if (sink_obj.con == 'hello') {
                        console.log('Received: ' + line);

                        if (++tas_download_count >= download_arr.length) {
                            tas_state = 'upload';
                        }
                    }
                    else {
                        for (var j = 0; j < upload_arr.length; j++) {
                            if (upload_arr[j].ctname == sink_obj.ctname) {
                                console.log('ACK : ' + line + ' <----');
                                break;
                            }
                        }

                        for (j = 0; j < download_arr.length; j++) {
                            if (download_arr[j].ctname == sink_obj.ctname) {
                                g_down_buf = JSON.stringify({id: download_arr[i].id, con: sink_obj.con});
                                console.log(g_down_buf + ' <----');
                                break;
                            }
                        }
                    }
                }
            }
        }
    }
}

function tas_watchdog() {
    if (tas_state == 'init') {
        upload_client = new net.Socket();

        upload_client.on('data', on_receive);

        upload_client.on('error', function(err) {
            console.log(err);
            tas_state = 'reconnect';
        });

        upload_client.on('close', function() {
            console.log('Connection closed');
            upload_client.destroy();
            tas_state = 'reconnect';
        });

        if (upload_client) {
            console.log('tas init ok');
            tas_state = 'init_thing';
        }
    }
    else if (tas_state == 'init_thing') {
        // init things
        
        tas_state = 'connect';
    }
    else if (tas_state == 'connect' || tas_state == 'reconnect') {
        upload_client.connect(useparentport, useparenthostname, function() {
            console.log('upload Connected');
            tas_download_count = 0;
            for (var i = 0; i < download_arr.length; i++) {
                console.log('download Connected - ' + download_arr[i].ctname + ' hello');
                var cin = {ctname: download_arr[i].ctname, con: 'hello'};
                upload_client.write(JSON.stringify(cin) + '<EOF>');
            }

            if (tas_download_count >= download_arr.length) {
                tas_state = 'upload';
            }
        });
    }
}

// Every 3 seconds, check if the TAS is not working
wdt.set_wdt(require('shortid').generate(), 3, tas_watchdog);

const Gpio = require('pigpio').Gpio;

// The number of microseconds it takes sound to travel 1cm at 20 degrees celcius
const MICROSECDONDS_PER_CM = 1e6/34321;
 
const trigger = new Gpio(20, {mode: Gpio.OUTPUT});          // GPIO23: trigger pin
const echo = new Gpio(21, {mode: Gpio.INPUT, alert: true}); // GPIO24: echo pin

const range_max = 600;  // maximum range for detection
const range_min = 0;  // minimum range for detection

var dist_0 = 0;
var dist_1 = 0;
var ultrasonic_update = true;

trigger.digitalWrite(0);

const watchHCSR04 = () => {
    let startTick;

    echo.on('alert', (level, tick) => {
        if (level == 1) {
            startTick = tick;
        } else {
            const endTick = tick;
            const diff = (endTick >> 0) - (startTick >> 0); // Unsigned 32 bit arithmetic
            // console.log(diff / 2 / MICROSECDONDS_PER_CM);
            dist_1 = (diff / 2 / MICROSECDONDS_PER_CM).toFixed(2);
            if (dist_1 >= range_max || dist_1 <= range_min)
                dist_1 =  -1;
        }
    });
};

watchHCSR04();
setInterval(() => {
    trigger.trigger(10, 1);

    // comment out the below if-else statement to update at every interval
    if (dist_1 > 23){
        con_data = 1;
    }
    else {
        con_data = 0;
    }
    if (ultrasonic_update) {
        if (tas_state=='upload') {
            for(var i = 0; i < upload_arr.length; i++) {
                if(upload_arr[i].id != "ultrasound") {
                    var cin = {ctname: upload_arr[i].ctname, con: con_data};
                    console.log("SEND : " + JSON.stringify(cin) + ' ---->')
                    upload_client.write(JSON.stringify(cin) + '<EOF>');
                    break;
                }
            }
        }
        dist_0 = dist_1;
    }
}, 1000);

Ultrasonic sensor dog food remaining amount of TAS conf.xml code.

XML
conf.xml code
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<m2m:conf xmlns:m2m="http://www.onem2m.org/xml/protocols" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <tas>
        <parenthostname>localhost</parenthostname>
        <parentport>3105</parentport>
    </tas>
    <upload>
        <ctname>remains</ctname>
        <id>remains#1</id>
    </upload>
</m2m:conf>

eat or not nCube conf.js code

JavaScript
Whether dogs eat food or not. nCube conf.js code of ultrasonic sensor.
/**
 * Created by Il Yeup, Ahn in KETI on 2017-02-23.
 */

/**
 * Copyright (c) 2018, OCEAN
 * All rights reserved.
 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
 * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission.
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

var ip = require("ip");

var conf = {};
var cse = {};
var ae = {};
var cnt_arr = [];
var sub_arr = [];
var acp = {};

conf.useprotocol = 'http'; // select one for 'http' or 'mqtt' or 'coap' or 'ws'

// build cse
cse.host        = '203.253.128.177';
cse.port        = '7579';
cse.name        = 'Mobius';
cse.id          = '/Mobius2';
cse.mqttport    = '1883';
cse.wsport      = '7577';

// build ae
ae.name         = 'walwal';

ae.id           = 'SgkP2YGD89v';

ae.parent       = '/' + cse.name;
ae.appid        = 'measure_co2';
ae.port         = '9727';
ae.bodytype     = 'json'; // select 'json' or 'xml' or 'cbor'
ae.tasport      = '3105';

// build cnt
var count = 0;
cnt_arr[count] = {};
cnt_arr[count].parent = '/' + cse.name + '/' + ae.name;
cnt_arr[count++].name = 'eat';

// build sub
count = 0;
// --------
sub_arr[count] = {};
sub_arr[count].parent = '/' + cse.name + '/' + ae.name + '/' + cnt_arr[0].name;
sub_arr[count].name = 'sub';
sub_arr[count++].nu = 'mqtt://' + cse.host + '/' + ae.id + '?ct=' + ae.bodytype; // mqtt

// build acp: not complete
acp.parent = '/' + cse.name + '/' + ae.name;
acp.name = 'acp-' + ae.name;
acp.id = ae.id;

conf.usesecure  = 'disable';

if(conf.usesecure === 'enable') {
    cse.mqttport = '8883';
}

conf.cse = cse;
conf.ae = ae;
conf.cnt = cnt_arr;
conf.sub = sub_arr;
conf.acp = acp;


module.exports = conf;

Whether dogs eat food or not. nCube conf.js code of ultrasonic sensor.

JavaScript
Whether dogs eat food or not. nCube conf.js code of ultrasonic sensor.
var net = require('net');
var util = require('util');
var fs = require('fs');
var xml2js = require('xml2js');

var wdt = require('./wdt');

var useparentport = '';
var useparenthostname = '';

var upload_arr = [];
var download_arr = [];

var conf = {};

// This is an async file read
fs.readFile('conf.xml', 'utf-8', function (err, data) {
    if (err) {
        console.log("FATAL An error occurred trying to read in the file: " + err);
        console.log("error : set to default for configuration")
    }
    else {
        var parser = new xml2js.Parser({explicitArray: false});
        parser.parseString(data, function (err, result) {
            if (err) {
                console.log("Parsing An error occurred trying to read in the file: " + err);
                console.log("error : set to default for configuration")
            }
            else {
                var jsonString = JSON.stringify(result);
                conf = JSON.parse(jsonString)['m2m:conf'];

                useparenthostname = conf.tas.parenthostname;
                useparentport = conf.tas.parentport;

                if (conf.upload != null) {
                    if (conf.upload['ctname'] != null) {
                        upload_arr[0] = conf.upload;
                    }
                    else {
                        upload_arr = conf.upload;
                    }
                }

                if (conf.download != null) {
                    if (conf.download['ctname'] != null) {
                        download_arr[0] = conf.download;
                    }
                    else {
                        download_arr = conf.download;
                    }
                }
            }
        });
    }
});

var tas_state = 'init';
var upload_client = null;
var t_count = 0;
var tas_download_count = 0;

function on_receive(data) {
    if (tas_state == 'connect' || tas_state == 'reconnect' || tas_state == 'upload') {
        var data_arr = data.toString().split('<EOF>');
        if (data_arr.length >= 2) {
            for (var i = 0; i < data_arr.length - 1; i++) {
                var line = data_arr[i];
                var sink_str = util.format('%s', line.toString());
                var sink_obj = JSON.parse(sink_str);

                if (sink_obj.ctname == null || sink_obj.con == null) {
                    console.log('Received: data format mismatch');
                }
                else {
                    if (sink_obj.con == 'hello') {
                        console.log('Received: ' + line);

                        if (++tas_download_count >= download_arr.length) {
                            tas_state = 'upload';
                        }
                    }
                    else {
                        for (var j = 0; j < upload_arr.length; j++) {
                            if (upload_arr[j].ctname == sink_obj.ctname) {
                                console.log('ACK : ' + line + ' <----');
                                break;
                            }
                        }

                        for (j = 0; j < download_arr.length; j++) {
                            if (download_arr[j].ctname == sink_obj.ctname) {
                                g_down_buf = JSON.stringify({id: download_arr[i].id, con: sink_obj.con});
                                console.log(g_down_buf + ' <----');
                                break;
                            }
                        }
                    }
                }
            }
        }
    }
}

function tas_watchdog() {
    if (tas_state == 'init') {
        upload_client = new net.Socket();

        upload_client.on('data', on_receive);

        upload_client.on('error', function(err) {
            console.log(err);
            tas_state = 'reconnect';
        });

        upload_client.on('close', function() {
            console.log('Connection closed');
            upload_client.destroy();
            tas_state = 'reconnect';
        });

        if (upload_client) {
            console.log('tas init ok');
            tas_state = 'init_thing';
        }
    }
    else if (tas_state == 'init_thing') {
        // init things
        
        tas_state = 'connect';
    }
    else if (tas_state == 'connect' || tas_state == 'reconnect') {
        upload_client.connect(useparentport, useparenthostname, function() {
            console.log('upload Connected');
            tas_download_count = 0;
            for (var i = 0; i < download_arr.length; i++) {
                console.log('download Connected - ' + download_arr[i].ctname + ' hello');
                var cin = {ctname: download_arr[i].ctname, con: 'hello'};
                upload_client.write(JSON.stringify(cin) + '<EOF>');
            }

            if (tas_download_count >= download_arr.length) {
                tas_state = 'upload';
            }
        });
    }
}

// Every 3 seconds, check if the TAS is not working
wdt.set_wdt(require('shortid').generate(), 3, tas_watchdog);

const Gpio = require('pigpio').Gpio;

// The number of microseconds it takes sound to travel 1cm at 20 degrees celcius
const MICROSECDONDS_PER_CM = 1e6/34321;
 
const trigger = new Gpio(20, {mode: Gpio.OUTPUT});          // GPIO20: trigger pin
const echo = new Gpio(21, {mode: Gpio.INPUT, alert: true}); // GPIO21: echo pin

const range_max = 600;  // maximum range for detection
const range_min = 0;  // minimum range for detection

var dist_0 = 0;
var dist_1 = 0;
var ultrasonic_update = true;

trigger.digitalWrite(0);

const watchHCSR04 = () => {
    let startTick;

    echo.on('alert', (level, tick) => {
        if (level == 1) {
            startTick = tick;
        } else {
            const endTick = tick;
            const diff = (endTick >> 0) - (startTick >> 0); // Unsigned 32 bit arithmetic
            // console.log(diff / 2 / MICROSECDONDS_PER_CM);
            dist_1 = (diff / 2 / MICROSECDONDS_PER_CM).toFixed(2);
            if (dist_1 >= range_max || dist_1 <= range_min)
                dist_1 =  -1;
        }
    });
};

watchHCSR04();
setInterval(() => {
    trigger.trigger(10, 1);

    // comment out the below if-else statement to update at every interval
    if (dist_1 > 23){
        con_data = 1;
    }
    else {
        con_data = 0;
    }
    if (ultrasonic_update) {
        if (tas_state=='upload') {
            for(var i = 0; i < upload_arr.length; i++) {
                if(upload_arr[i].id != "ultrasound") {
                    var cin = {ctname: upload_arr[i].ctname, con: con_data};
                    console.log("SEND : " + JSON.stringify(cin) + ' ---->')
                    upload_client.write(JSON.stringify(cin) + '<EOF>');
                    break;
                }
            }
        }
        dist_0 = dist_1;
    }
}, 1000);

GPS alarm

Python
Read latitude and longitude to sense dog escape.
If it escape send alarm message to mobius.
import time
import board
import busio
import requests
from parse import *
import adafruit_gps
import serial
uart = serial.Serial("/dev/ttyS0", baudrate=9600, timeout=10)

gps = adafruit_gps.GPS(uart)  # Use UART/pyserial



#Turn on only GPRMC
gps.send_command(b'PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0')
gps.send_command(b'PMTK220,2000')
timestamp = time.monotonic()
out_alarm = False

while True:
    data = gps.read(64)
    data_string = "".join([chr(b) for b in data])
    list = data_string.split(',')
    print(list)
    if "V" in list:
        print("Can't read base_GPS")
    elif "A" in list:
        position = list.index("A")
        if (len(list[position:]) > 3):
            latitude_temp = list[position+1]
            longitude_temp = list[position+3]
            print(latitude_temp)
            base_latitude = int(latitude_temp[:2]) + (float(latitude_temp[2:]) / 60)
            base_longitude = int(longitude_temp[:2]) + (float(longitude_temp[2:]) / 60)
            print(base_latitude, "  ", base_longitude)
            break


while True:
    data = gps.read(64) 
    if data is not None:
        data_string = "".join([chr(b) for b in data])
        list = data_string.split(',')
        time.sleep(0.5)

        if "V" in list:
           position = list.index("V")
           print("Can't read GPS")
        elif "A" in list:
            position = list.index("A")
            if (len(list[position:]) > 3):
                latitude_temp = list[position+1]
                longitude_temp = list[position+3]
                latitude = int(latitude_temp[:2]) + (float(latitude_temp[2:]) / 60)
                print(longitude_temp[2:])
                longitude = int(longitude_temp[:2]) + (float(longitude_temp[2:]) / 60)
                distance = (abs(base_latitude - latitude) + abs(base_longitude - longitude)) 
                #print(distance)
                if distance > 0.0004 and distance < 1:
                    out_alarm = True
                    break

            

        if time.monotonic() - timestamp > 5:
            gps.send_command(b"PMTK605")  
            timestamp = time.monotonic()

    
        if out_alarm == True:
            mobius_data = "Out!"
            url = 'http://203.253.128.177:7579/Mobius/walwal/alert'
            headers =   {
                        'Accept':'application/json',
                        'X-M2M-RI':'12345',
                        'X-M2M-Origin':'XXXXXXXXXXX', # change to your aei
                        'Content-Type':'application/vnd.onem2m-res+json; ty=4'
                    }

            data =   {
                    "m2m:cin": {
                        "con": "1"
                    }
                }

            r = requests.post(url, headers=headers, json=data)

            try:
                r.raise_for_status()
                print(r)
            except Exception as exc:
                print('There was a problem: %s' % (exc))

nCube 'conf.js' for Training Machine

JavaScript
This is the javascript code setting file for the training machine.
/**
 * Created by Il Yeup, Ahn in KETI on 2017-02-23.
 */

/**
 * Copyright (c) 2018, OCEAN
 * All rights reserved.
 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
 * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission.
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Modified by 'Giyeong Hong'
 */
 

var ip = require("ip");

var conf = {};
var cse = {};
var ae = {};
var cnt_arr = [];
var sub_arr = [];
var acp = {};

conf.useprotocol = 'http'; // select one for 'http' or 'mqtt' or 'coap' or 'ws'

// build cse
cse.host        = '203.253.128.177';
cse.port        = '7579';
cse.name        = 'Mobius';
cse.id          = '/Mobius2';
cse.mqttport    = '1883';
cse.wsport      = '7577';

// build ae
ae.name         = 'walwal';

ae.id           = 'SgkP2YGD89v';

ae.parent       = '/' + cse.name;
ae.appid        = 'measure_co2';
ae.port         = '9727';
ae.bodytype     = 'json'; // select 'json' or 'xml' or 'cbor'
ae.tasport      = '3105';

// build cnt
var count = 0;
cnt_arr[count] = {};
cnt_arr[count].parent = '/' + cse.name + '/' + ae.name;
cnt_arr[count++].name = 'training';
// cnt_arr[count] = {};
// cnt_arr[count].parent = '/' + cse.name + '/' + ae.name;
// cnt_arr[count++].name = 'touch';
// cnt_arr[count] = {};
// cnt_arr[count].parent = '/' + cse.name + '/' + ae.name;
// cnt_arr[count++].name = 'sound';
// cnt_arr[count] = {};
// cnt_arr[count].parent = '/' + cse.name + '/' + ae.name;
// cnt_arr[count++].name = 'pir';
// cnt_arr[count] = {};
// cnt_arr[count].parent = '/' + cse.name + '/' + ae.name;
// cnt_arr[count++].name = 'ultrasonic';
// cnt_arr[count] = {};
// cnt_arr[count].parent = '/' + cse.name + '/' + ae.name;
// cnt_arr[count++].name = 'temp';
// cnt_arr[count] = {};
// cnt_arr[count].parent = '/' + cse.name + '/' + ae.name;
// cnt_arr[count++].name = 'accel';
// cnt_arr[count] = {};
// cnt_arr[count].parent = '/' + cse.name + '/' + ae.name;
// cnt_arr[count++].name = 'light';
// cnt_arr[count] = {};
// cnt_arr[count].parent = '/' + cse.name + '/' + ae.name;
// cnt_arr[count++].name = 'dust';
// cnt_arr[count] = {};
// cnt_arr[count].parent = '/' + cse.name + '/' + ae.name;
// cnt_arr[count++].name = 'ledm';

// build sub
count = 0;
//sub_arr[count] = {};
//sub_arr[count].parent = '/' + cse.name + '/' + ae.name + '/' + cnt_arr[1].name;
//sub_arr[count].name = 'sub-ctrl';
//sub_arr[count++].nu = 'mqtt://' + cse.host + '/' + ae.id;




// --------
sub_arr[count] = {};
sub_arr[count].parent = '/' + cse.name + '/' + ae.name + '/' + cnt_arr[0].name;
sub_arr[count].name = 'sub';
sub_arr[count++].nu = 'mqtt://' + cse.host + '/' + ae.id + '?ct=' + ae.bodytype; // mqtt




//sub_arr[count++].nu = 'http://' + ip.address() + ':' + ae.port + '/noti?ct=json'; // http
//sub_arr[count++].nu = 'Mobius/'+ae.name; // mqtt
// --------

/*// --------
sub_arr[count] = {};
sub_arr[count].parent = '/' + cse.name + '/' + ae.name + '/' + cnt_arr[1].name;
sub_arr[count].name = 'sub2';
//sub_arr[count++].nu = 'http://' + ip.address() + ':' + ae.port + '/noti?ct=json'; // http
//sub_arr[count++].nu = 'mqtt://' + cse.host + '/' + ae.id + '?rcn=9&ct=' + ae.bodytype; // mqtt
sub_arr[count++].nu = 'mqtt://' + cse.host + '/' + ae.id + '?ct=json'; // mqtt
// -------- */

// build acp: not complete
acp.parent = '/' + cse.name + '/' + ae.name;
acp.name = 'acp-' + ae.name;
acp.id = ae.id;


conf.usesecure  = 'disable';

if(conf.usesecure === 'enable') {
    cse.mqttport = '8883';
}

conf.cse = cse;
conf.ae = ae;
conf.cnt = cnt_arr;
conf.sub = sub_arr;
conf.acp = acp;


module.exports = conf;

"http_app.js" file for training machines.

JavaScript
Check 'cin value' from Mobius server.
If it meets the conditions, the training is conducted.
/**
 * Copyright (c) 2018, OCEAN
 * All rights reserved.
 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
 * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission.
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * Created by ryeubi on 2015-08-31.
 */

const spawn = require('child_process').spawn;

var http = require('http');
var express = require('express');
var fs = require('fs');
var bodyParser = require('body-parser');
var mqtt = require('mqtt');
var util = require('util');
var xml2js = require('xml2js');
var url = require('url');
var ip = require('ip');
var shortid = require('shortid');
var cbor = require('cbor');

global.sh_adn = require('./http_adn');
var noti = require('./noti');
var tas = require('./thyme_tas');

var HTTP_SUBSCRIPTION_ENABLE = 0;
var MQTT_SUBSCRIPTION_ENABLE = 0;

var app = express();

//app.use(bodyParser.urlencoded({ extended: true }));
//app.use(bodyParser.json());
//app.use(bodyParser.json({ type: 'application/*+json' }));
//app.use(bodyParser.text({ type: 'application/*+xml' }));

// ?????? ????????.
var server = null;
var noti_topic = '';

// ready for mqtt
for(var i = 0; i < conf.sub.length; i++) {
    if(conf.sub[i].name != null) {
        if(url.parse(conf.sub[i].nu).protocol === 'http:') {
            HTTP_SUBSCRIPTION_ENABLE = 1;
            if(url.parse(conf.sub[i]['nu']).hostname === 'autoset') {
                conf.sub[i]['nu'] = 'http://' + ip.address() + ':' + conf.ae.port + url.parse(conf.sub[i]['nu']).pathname;
            }
        }
        else if(url.parse(conf.sub[i].nu).protocol === 'mqtt:') {
            MQTT_SUBSCRIPTION_ENABLE = 1;
        }
        else {
            //console.log('notification uri of subscription is not supported');
            //process.exit();
        }
    }
}

var return_count = 0;
var request_count = 0;

function ready_for_notification() {
    if(HTTP_SUBSCRIPTION_ENABLE == 1) {
        server = http.createServer(app);
        server.listen(conf.ae.port, function () {
            console.log('http_server running at ' + conf.ae.port + ' port');
        });
    }

    if(MQTT_SUBSCRIPTION_ENABLE == 1) {
        for(var i = 0; i < conf.sub.length; i++) {
            if (conf.sub[i].name != null) {
                if (url.parse(conf.sub[i].nu).protocol === 'mqtt:') {
                    if (url.parse(conf.sub[i]['nu']).hostname === 'autoset') {
                        conf.sub[i]['nu'] = 'mqtt://' + conf.cse.host + '/' + conf.ae.id;
                        noti_topic = util.format('/oneM2M/req/+/%s/#', conf.ae.id);
                    }
                    else if (url.parse(conf.sub[i]['nu']).hostname === conf.cse.host) {
                        noti_topic = util.format('/oneM2M/req/+/%s/#', conf.ae.id);
                    }
                    else {
                        noti_topic = util.format('%s', url.parse(conf.sub[i].nu).pathname);
                    }
                }
            }
        }
        mqtt_connect(conf.cse.host, noti_topic);
    }
}

function ae_response_action(status, res_body, callback) {
    var aeid = res_body['m2m:ae']['aei'];
    conf.ae.id = aeid;
    callback(status, aeid);
}

function create_cnt_all(count, callback) {
    if(conf.cnt.length == 0) {
        callback(2001, count);
    }
    else {
        var parent = conf.cnt[count].parent;
        var rn = conf.cnt[count].name;
        sh_adn.crtct(parent, rn, count, function (rsc, res_body, count) {
            if(rsc == 5106 || rsc == 2001 || rsc == 4105) {
                callback(rsc, count);
            }
            else {
                callback('9999', count);
            }
        });
    }
}

function delete_sub_all(count, callback) {
    if(conf.sub.length == 0) {
        callback(2001, count);
    }
    else {
        var target = conf.sub[count].parent + '/' + conf.sub[count].name;
        sh_adn.delsub(target, count, function (rsc, res_body, count) {
            if(rsc == 5106 || rsc == 2002 || rsc == 2000 || rsc == 4105 || rsc == 4004) {
                callback(rsc, count);
            }
            else {
                callback('9999', count);
            }
        });
    }
}

function create_sub_all(count, callback) {
    if(conf.sub.length == 0) {
        callback(2001, count);
    }
    else {
        var parent = conf.sub[count].parent;
        var rn = conf.sub[count].name;
        var nu = conf.sub[count].nu;
        sh_adn.crtsub(parent, rn, nu, count, function (rsc, res_body, count) {
            if(rsc == 5106 || rsc == 2001 || rsc == 4105) {
                callback(rsc, count);
            }
            else {
                callback('9999', count);
            }
        });
    }
}

function http_watchdog() {
    if (sh_state === 'crtae') {
        console.log('[sh_state] : ' + sh_state);
        sh_adn.crtae(conf.ae.parent, conf.ae.name, conf.ae.appid, function (status, res_body) {
            console.log(res_body);
            if (status == 2001) {
                ae_response_action(status, res_body, function (status, aeid) {
                    console.log('x-m2m-rsc : ' + status + ' - ' + aeid + ' <----');
                    sh_state = 'crtct';
                    request_count = 0;
                    return_count = 0;
                });
            }
            else if (status == 5106 || status == 4105) {
                console.log('x-m2m-rsc : ' + status + ' <----');
                sh_state = 'rtvae'
            }
        });
    }
    else if (sh_state === 'rtvae') {
        if (conf.ae.id === 'S') {
            conf.ae.id = 'S' + shortid.generate();
        }

        console.log('[sh_state] : ' + sh_state);
        sh_adn.rtvae(conf.ae.parent + '/' + conf.ae.name, function (status, res_body) {
            if (status == 2000) {
                var aeid = res_body['m2m:ae']['aei'];
                console.log('x-m2m-rsc : ' + status + ' - ' + aeid + ' <----');

                if(conf.ae.id != aeid && conf.ae.id != ('/'+aeid)) {
                    console.log('AE-ID created is ' + aeid + ' not equal to device AE-ID is ' + conf.ae.id);
                }
                else {
                    sh_state = 'crtct';
                    request_count = 0;
                    return_count = 0;
                }
            }
            else {
                console.log('x-m2m-rsc : ' + status + ' <----');
            }
        });
    }
    else if (sh_state === 'crtct') {
        console.log('[sh_state] : ' + sh_state);
        if(return_count == 0) {
            create_cnt_all(request_count, function (status, count) {
                request_count = ++count;
                return_count = 0;
                if (conf.cnt.length <= count) {
                    sh_state = 'delsub';
                    request_count = 0;
                    return_count = 0;
                }
            });
        }
        return_count++;
        if(return_count >= 3) {
            return_count = 0;
        }
    }
    else if (sh_state === 'delsub') {
        console.log('[sh_state] : ' + sh_state);
        if(return_count == 0) {
            delete_sub_all(request_count, function (status, count) {
                request_count = ++count;
                return_count = 0;
                if (conf.sub.length <= count) {
                    sh_state = 'crtsub';
                    request_count = 0;
                    return_count = 0;
                }
            });
        }
        return_count++;
        if(return_count >= 3) {
            return_count = 0;
        }
    }
    else if (sh_state === 'crtsub') {
        console.log('[sh_state] : ' + sh_state);
        if(return_count == 0) {
            create_sub_all(request_count, function (status, count) {
                request_count = ++count;
                return_count = 0;
                if (conf.sub.length <= count) {
                    sh_state = 'crtci';

                    ready_for_notification();

                    tas.ready();

                    // var _ae = {};
                    // _ae.id = conf.ae.id;
                    // fs.writeFileSync('aei.json', JSON.stringify(_ae, null, 4), 'utf8');
                }
            });
        }
        return_count++;
        if(return_count >= 3) {
            return_count = 0;
        }
    }
    else if (sh_state === 'crtci') {

    }
}

wdt.set_wdt(require('shortid').generate(), 2, http_watchdog);


// for notification
//var xmlParser = bodyParser.text({ type: '*/*' });


function mqtt_connect(serverip, noti_topic) {
    if(mqtt_client == null) {
        if (conf.usesecure === 'disable') {
            var connectOptions = {
                host: serverip,
                port: conf.cse.mqttport,
//              username: 'keti',
//              password: 'keti123',
                protocol: "mqtt",
                keepalive: 10,
//              clientId: serverUID,
                protocolId: "MQTT",
                protocolVersion: 4,
                clean: true,
                reconnectPeriod: 2000,
                connectTimeout: 2000,
                rejectUnauthorized: false
            };
        }
        else {
            connectOptions = {
                host: serverip,
                port: conf.cse.mqttport,
                protocol: "mqtts",
                keepalive: 10,
//              clientId: serverUID,
                protocolId: "MQTT",
                protocolVersion: 4,
                clean: true,
                reconnectPeriod: 2000,
                connectTimeout: 2000,
                key: fs.readFileSync("./server-key.pem"),
                cert: fs.readFileSync("./server-crt.pem"),
                rejectUnauthorized: false
            };
        }

        mqtt_client = mqtt.connect(connectOptions);
    }

    mqtt_client.on('connect', function () {
        mqtt_client.subscribe(noti_topic);
        console.log('[mqtt_connect] noti_topic : ' + noti_topic);
    });

    mqtt_client.on('message', function (topic, message) {

        var topic_arr = topic.split("/");

        var bodytype = conf.ae.bodytype;
        if(topic_arr[5] != null) {
            bodytype = (topic_arr[5] === 'xml') ? topic_arr[5] : ((topic_arr[5] === 'json') ? topic_arr[5] : ((topic_arr[5] === 'cbor') ? topic_arr[5] : 'json'));
        }

        if(topic_arr[1] === 'oneM2M' && topic_arr[2] === 'req' && topic_arr[4] === conf.ae.id) {
            var temp_string = message.toString();
            console.log(temp_string);
/////////////////////////////////////////////////////////////////////////////////////////////////////////
            var con_value = Number(temp_string[temp_string.indexOf('con":"') + 6]) //number type
            console.log("Received data : " + con_value);

            switch(con_value) {
                case 1:
                    console.log("Sit");

                    var spawn = require('child_process').spawn;
            
                    var result = spawn('python3.7', ['./instruct.py', String(con_value)]); 
                    
                    result.stdout.on('data', function(data) { console.log(data.toString()); });
                    
                    result.stderr.on('data', function(data) { console.log(data.toString()); });

                    break;
                case 2:
                    console.log("Wait");

                    var spawn = require('child_process').spawn;
            
                    var result = spawn('python3.7', ['./instruct.py', String(con_value)]); 
                    
                    result.stdout.on('data', function(data) { console.log(data.toString()); });
                    
                    result.stderr.on('data', function(data) { console.log(data.toString()); });

                    break;
                default:
                    console.log("Not working");
                    break;
            }
            
/////////////////////////////////////////////////////////////////////////////////////////////////////////
            if(bodytype === 'xml') {
                var parser = new xml2js.Parser({explicitArray: false});
                parser.parseString(message.toString(), function (err, jsonObj) {
                    if (err) {
                        console.log('[mqtt noti xml2js parser error]');
                    }
                    else {
                        noti.mqtt_noti_action(topic_arr, jsonObj);
                    }
                });
            }
            else if(bodytype === 'cbor') {
                var encoded = message.toString();
                cbor.decodeFirst(encoded, function(err, jsonObj) {
                    if (err) {
                        console.log('[mqtt noti cbor parser error]');
                    }
                    else {
                        noti.mqtt_noti_action(topic_arr, jsonObj);
                    }
                });
            }
            else { // json
                var jsonObj = JSON.parse(message.toString());

                if (jsonObj['m2m:rqp'] == null) {
                    jsonObj['m2m:rqp'] = jsonObj;
                }
                noti.mqtt_noti_action(topic_arr, jsonObj);
            }
        }
        else {
            console.log('topic is not supported');
        }
    });

    mqtt_client.on('error', function (err) {
        console.log(err.message);
    });
}

var onem2mParser = bodyParser.text(
    {
        limit: '1mb',
        type: 'application/onem2m-resource+xml;application/xml;application/json;application/vnd.onem2m-res+xml;application/vnd.onem2m-res+json'
    }
);

var noti_count = 0;

app.post('/:resourcename0', onem2mParser, function(request, response) {
    var fullBody = '';
    request.on('data', function (chunk) {
        fullBody += chunk.toString();
    });
    request.on('end', function () {
        request.body = fullBody;

        console.log(fullBody);

        for (var i = 0; i < conf.sub.length; i++) {
            if (conf.sub[i]['nu'] != null) {
                if(url.parse(conf.sub[i].nu).protocol === 'http:') {
                    var nu_path = url.parse(conf.sub[i]['nu']).pathname.toString().split('/')[1];
                    if (nu_path === request.params.resourcename0) {
                        var content_type = request.headers['content-type'];
                        if(content_type.includes('xml')) {
                            var bodytype = 'xml';
                        }
                        else if(content_type.includes('cbor')) {
                            bodytype = 'cbor';
                        }
                        else {
                            bodytype = 'json';
                        }
                        if (bodytype === 'json') {
                            try {
                                var pc = JSON.parse(request.body);
                                var rqi = request.headers['x-m2m-ri'];

                                noti.http_noti_action(rqi, pc, 'json', response);
                            }
                            catch (e) {
                                console.log(e);
                            }
                        }
                        else if(bodytype === 'cbor') {
                            var encoded = request.body;
                            cbor.decodeFirst(encoded, function(err, pc) {
                                if (err) {
                                    console.log('[http noti cbor parser error]');
                                }
                                else {
                                    var rqi = request.headers['x-m2m-ri'];

                                    noti.http_noti_action(rqi, pc, 'cbor', response);
                                }
                            });
                        }
                        else {
                            var parser = new xml2js.Parser({explicitArray: false});
                            parser.parseString(request.body, function (err, pc) {
                                if (err) {
                                    console.log('[http noti xml2js parser error]');
                                }
                                else {
                                    var rqi = request.headers['x-m2m-ri'];

                                    noti.http_noti_action(rqi, pc, 'xml', response);
                                }
                            });
                        }
                        break;
                    }
                }
            }
        }
    });
});

app.get('/conf', onem2mParser, function(request, response, next) {

});

/* for testing
app.use(function(request, response, next) {
    var fullBody = '';
    request.on('data', function (chunk) {
        fullBody += chunk.toString();
    });
    request.on('end', function () {
        request.body = fullBody;

        console.log(fullBody);

        response.status(200).send('');
    });
});
*/

'instruct.py' file for training machine

Python
The command is delivered through 'http_app.js'
Thereafter, a command is delivered to Arduino through UART communication for device startup.
import sys
import time
import serial
import os

def instruct_send(code):
    while True:
        code = str(code).encode('utf-8')
        temp = arduino.write(code)
            
        if temp > 2000:
            break

if __name__ == '__main__':
    arduino = serial.Serial('/dev/ttyACM0', 9600)
    
    arduino.flush()
    
    instruct_send(1) # send to arduino value of 1 or 2
    print("Sit1 OK")
    
    os.system('omxplayer sit.m4a &')
    import sit
    file_sit = 'sit.py'
    sit_return = sit.return_value
    sit_return = bool(sit_return)

    # sit_return = True ############################################# temp value of return sit test

    # training result and arduino excute
    if sys.argv[1] == '1': #if argv is sit?
        if sit_return == True: #<<sit mode>> return value true?
            instruct_send(5) #arduino 'give snack'
            print("GIVE SNACK OK(SIT)")
            instruct_send(3) #arduino return sit
            print("Sit2 OK(SUCCEED)")
            arduino.flush()
        elif sit_return == False: #<<sit mode>> return value false?
            instruct_send(6)
            print("Dummy for control Error")
            instruct_send(3) #arduino 'sit2'
            print("Sit2 OK(FAILED)")
            arduino.flush()
    elif sys.argv[1] == '2':
        if sit_return == True: #<<sit mode>> return value true??
            instruct_send(2) #arduino 'wait1'            
            print("WAIT1 OK(SUCCEED)")
            os.system('omxplayer wait.m4a &')            
            import wait
            file_wait = 'wait.py'
            wait_return = wait.return_value
            wait_return = bool(wait_return)
            # wait_return = False ######################################################## temp value of return wait test
            if wait_return == True: #<<wait mode>> return value true??
                instruct_send(5) #arduino 'give snack'
                print("GIVE SNACK OK(WAIT)")
                instruct_send(4)
                print("WAIT2 OK(SUCCEED)")
                arduino.flush()
            elif wait_return == False: #<<wait mode>> return value false?
                instruct_send(6)
                print("Dummy for control Error")
                instruct_send(4)
                print("WAIT2 OK(FAILED)")
                arduino.flush()
        elif sit_return == False:
            instruct_send(6)
            print("Dummy for control Error")
            instruct_send(3) #arduino 'sit2'
            print("SIT2 OK(FAILED IN WAIT)")
            arduino.flush()

'TotalTraining.ino' code for actual device startup.

Arduino
It is a code that receives parameter through 'instruct.py' and actually implements the corresponding action.
#include <Servo.h> 

const int servoPin1 = 2;
const int servoPin2 = 3;
const int servoPin3 = 4;
const int servoPin4 = 5;
const int servoPin5 = 6;

Servo servo1;
Servo servo2;
Servo servo3;
Servo servo4;
Servo servo5;

int angle1 = 0;
int angle2 = 180;
int angle3 = 180;
int angle4 = 0;
int angle5 = 0;

void setup() {
  Serial.begin(9600);
  servo1.attach(servoPin1);
  servo2.attach(servoPin2); 
  servo3.attach(servoPin3);
  servo4.attach(servoPin4); 
  servo5.attach(servoPin5);

  servo1.write(0); 
  servo2.write(180); 
  servo3.write(180); 
  servo4.write(0);
  servo5.write(0);
}

int i;
int j;
int k;

//angle1 = 0~90
//angle2 = 90~180
//angle3 = 90~180
//angle4 = 0~90

void training_sit_1() {
  for(i = 0; i < 45; i++) {
    servo1.write(i);
    servo2.write(180 - i);
    delay(20);
  }
  
  for(j = 0; j < 135; j++) {
    servo3.write(180 - j);
    servo4.write(j);
    delay(20);
  }
}

void training_sit_2() {
  for(j = 135; j > 0; j--) {
    servo3.write(180 - j);
    servo4.write(j);
    delay(20);
  }

  for(i = 45; i > 0; i--) {
    servo1.write(i);
    servo2.write(180 - i);
    delay(20);
  }
}

void training_wait_1() {
  for(j = 135; j > 60; j--) {
    servo3.write(180 - j);
    servo4.write(j);
    delay(20);
  }

  for(i = 45; i < 60; i++) {
    servo1.write(i);
    servo2.write(180 - i);
    delay(20);
  }
  
}

void training_wait_2() {
  for(i = 60; i > 0; i--) {
    servo1.write(i);
    servo2.write(180 - i);
    delay(20);
  } 
  
  for(j = 70; j > 0; j--) {
    servo3.write(180 - j);
    servo4.write(j);
    delay(20);
  }
}

void give_snack() {
  for(k = 0; k < 180; k++) {
    servo5.write(k);
    delay(20);
  }

  for(k = 180; k > 0; k--) {
    servo5.write(k);
    delay(20);
  }
}

void dummy() {
  for(k = 0; k < 180; k++) {
    servo5.write(0);
    delay(20);
  }

  for(k = 180; k > 0; k--) {
    servo5.write(0);
    delay(20);
  }
}

void loop() {
  while (Serial.available() > 0) {
    char c = Serial.read();
    Serial.print(c);
    switch(c) {
      case '1':
        training_sit_1(); //  (  )
        while(Serial.available() > 0){
          Serial.read();
          c = 0;
          Serial.flush();
      }
        break;
      case '2':
        training_wait_1();//  (   ,   )
        dummy();
        while(Serial.available() > 0){
          Serial.read();
          c = 0;
          Serial.flush();
      }
        break;
      case '3':
        training_sit_2(); //  
        while(Serial.available() > 0){
          Serial.read();
          c = 0;
          Serial.flush();
      }
        break;
      case '4':
        training_wait_2(); //  
        while(Serial.available() > 0){
          Serial.read();
          c = 0;
          Serial.flush();
      }
        break;
      case '5': // 
        give_snack();
        while(Serial.available() > 0){
          Serial.read();
          c = 0;
          Serial.flush();
      }
        break;
      case '6': // 
        dummy();
        while(Serial.available() > 0){
          Serial.read();
          c = 0;
          Serial.flush();
      }
        break;
      default:
        while(Serial.available() > 0){
          Serial.read();
          c = 0;
          Serial.flush();
      }
        break;
    }
  }
}

Android MainActivity.java for Mobius App

Java
MainActivity.java

This is the app's vital code.

MQTT API is to receive real-time information.
- Subscribe to Topic to receive real-time information and listen to automatic reception (subscribe)
- After receiving the real-time information, I received the data well, but it's a response request (publish)
package sch.iot.onem2mapp;

import android.app.NotificationChannel; // added by S. Lee, SCH Univ.
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.graphics.Color;
import android.net.Uri;
import android.os.Build;
import android.os.Handler;

import android.support.v4.app.NotificationCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.Switch;
import android.widget.TextView;
import android.widget.ToggleButton;

import org.eclipse.paho.android.service.MqttAndroidClient;
import org.eclipse.paho.client.mqttv3.IMqttActionListener;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.IMqttToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
import fr.arnaudguyon.xmltojsonlib. XmlToJson;


import static sch.iot.onem2mapp.R.layout.activity_main;

public class MainActivity extends AppCompatActivity implements Button.OnClickListener, CompoundButton.OnCheckedChangeListener {
    public Button btnRetrieve;
    public Switch Switch_MQTT;
    public TextView textViewData;

    // added by by S. Lee, SCH Univ.
    public TextView textTrain;
    public TextView textRemains;
    public TextView textEat;
    public TextView textAlert;
    public TextView textSuccess;

    public ToggleButton btn_train;
    public ToggleButton btnSitdown;
    public ToggleButton btnWait;

    public Handler handler;
    public ToggleButton btnAddr_Set;

    private static CSEBase csebase = new CSEBase();
    private static AE ae = new AE();
    private static String TAG = "MainActivity";
    private String MQTTPort = "1883";

    // Modify this variable associated with your AE name in Mobius, by J. Yun, SCH Univ.
    private String ServiceAEName = "walwal";

    private String MQTT_Req_Topic = "";
    private String MQTT_Resp_Topic = "";
    private MqttAndroidClient mqttClient = null;
    private EditText EditText_Address =null;
    private String Mobius_Address ="";

    // added b

    private static final String PRIMARY_CHANNEL_ID_1 = "primary_notification_channel_1";
    private static final String PRIMARY_CHANNEL_ID_2 = "primary_notification_channel_2";
    private static final String PRIMARY_CHANNEL_ID_3 = "primary_notification_channel_3";
    private static final String PRIMARY_CHANNEL_ID_4 = "primary_notification_channel_4";
    private static final String PRIMARY_CHANNEL_ID_5 = "primary_notification_channel_5";
    private static final String PRIMARY_CHANNEL_ID_6 = "primary_notification_channel_6";

    private NotificationManager mNotificationManager;

    private static final int NOTIFICATION_ID_1 = 0;
    private static final int NOTIFICATION_ID_2 = 0;
    private static final int NOTIFICATION_ID_3 = 0;
    private static final int NOTIFICATION_ID_4 = 0;
    private static final int NOTIFICATION_ID_5 = 0;
    private static final int NOTIFICATION_ID_6 = 0;

    public Button button_notify_1;
    public Button button_notify_2;
    public Button button_notify_3;
    public Button button_notify_4;
    public Button button_notify_5;
    public Button button_notify_6;

    // Main
    public MainActivity() {
        handler = new Handler();
    }

    /* onCreate */
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(activity_main);

        btnRetrieve = findViewById(R.id.btnRetrieve);
        Switch_MQTT = findViewById(R.id.switch_mqtt);
        textViewData = findViewById(R.id.textViewData);
        EditText_Address = findViewById(R.id.editText);
        btnAddr_Set = findViewById(R.id.toggleButton_Addr);

        btn_train = findViewById(R.id.btn_train);
        btnSitdown =  findViewById(R.id.btnSitdown);
        btnWait =  findViewById(R.id.btnWait);

        textRemains = findViewById(R.id.textRemains);
        textEat = findViewById(R.id.textEat);
        textAlert = findViewById(R.id.textAlert);
        textSuccess = findViewById(R.id.textSuccess);


        btnRetrieve.setOnClickListener(this);
        Switch_MQTT.setOnCheckedChangeListener(this);
        btn_train.setOnClickListener(this);
        btnWait.setOnClickListener(this);
        btnSitdown.setOnClickListener(this);
        btnAddr_Set.setOnClickListener(this);


        // added by by S. Lee, SCH Univ.
        button_notify_1 = findViewById(R.id.notify_1);
        button_notify_2 = findViewById(R.id.notify_2);
        button_notify_3 = findViewById(R.id.notify_3);
        button_notify_4 = findViewById(R.id.notify_4);
        button_notify_5 = findViewById(R.id.notify_5);
        button_notify_6 = findViewById(R.id.notify_6);
        btnAddr_Set.setFocusable(true);

        btnSitdown.setVisibility(View.INVISIBLE);
        btnWait.setVisibility(View.INVISIBLE);

        // Create AE and Get AEID

        button_notify_1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                sendNotification_1();
            }
        });
        button_notify_2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                sendNotification_2();
            }
        });
        button_notify_3.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                sendNotification_3();
            }
        });
        button_notify_4.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                sendNotification_4();
            }
        });
        button_notify_5.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                sendNotification_5();
            }
        });
        button_notify_6.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                sendNotification_6();
            }
        });
        createNotificationChannel();

        btnAddr_Set.performClick();
        new Handler().postDelayed(new Runnable()
        {
            @Override
            public void run()
            {
                btnRetrieve.performClick();

                new Handler().postDelayed(new Runnable()
                {
                    @Override
                    public void run()
                    {
                        Switch_MQTT.performClick();
                    }
                }, 600);
            }
        }, 600);

    }
    /* AE Create for Androdi AE */
    public void GetAEInfo() {

        // You can put the IP address directly in code,
        // but also get it from EditText window
        Mobius_Address = EditText_Address.getText().toString();
//         csebase.setInfo(Mobius_Address,"7579","Mobius","1883");
        csebase.setInfo("203.253.128.177","7579","Mobius","1883");

        // AE Create for Android AE
        ae.setAppName("ncubeapp");
        aeCreateRequest aeCreate = new aeCreateRequest();
        aeCreate.setReceiver(new IReceived() {
            public void getResponseBody(final String msg) {
                handler.post(new Runnable() {
                    public void run() {
                        Log.d(TAG, "** AE Create ResponseCode[" + msg +"]");
                        if( Integer.parseInt(msg) == 201 ){
                            MQTT_Req_Topic = "/oneM2M/req/Mobius2/"+ae.getAEid()+"_sub"+"/#";
                            MQTT_Resp_Topic = "/oneM2M/resp/Mobius2/"+ae.getAEid()+"_sub"+"/json";
                            Log.d(TAG, "ReqTopic["+ MQTT_Req_Topic+"]");
                            Log.d(TAG, "ResTopic["+ MQTT_Resp_Topic+"]");
                        }
                        else { // If AE is Exist , GET AEID
                            aeRetrieveRequest aeRetrive = new aeRetrieveRequest();
                            aeRetrive.setReceiver(new IReceived() {
                                public void getResponseBody(final String resmsg) {
                                    handler.post(new Runnable() {
                                        public void run() {
                                            Log.d(TAG, "** AE Retrive ResponseCode[" + resmsg +"]");
                                            MQTT_Req_Topic = "/oneM2M/req/Mobius2/"+ae.getAEid()+"_sub"+"/#";
                                            MQTT_Resp_Topic = "/oneM2M/resp/Mobius2/"+ae.getAEid()+"_sub"+"/json";
                                            Log.d(TAG, "ReqTopic["+ MQTT_Req_Topic+"]");
                                            Log.d(TAG, "ResTopic["+ MQTT_Resp_Topic+"]");
                                        }
                                    });
                                }
                            });
                            aeRetrive.start();
                        }
                    }
                });
            }
        });
        aeCreate.start();
    }

    // Switch - Get MQTT, by J. Yun, SCH Univ.

    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {

        if (isChecked) {
            Log.d(TAG, "MQTT Create");
            MQTT_Create(true);
        } else {
            Log.d(TAG, "MQTT Close");
            MQTT_Create(false);
        }
    }



    /* MQTT Subscription */
    public void MQTT_Create(boolean mtqqStart) {
        if (mtqqStart && mqttClient == null) {
            /* Subscription Resource Create to Yellow Turtle */
            // added by S. Lee, SCH Univ.

            SubscribeResource

            subcribeResource = new SubscribeResource("remains");
            subcribeResource.setReceiver(new IReceived() {
                public void getResponseBody(final String msg) {
                    handler.post(new Runnable() {
                        public void run() {
                            textViewData.setText("**** Subscription Resource Creation Response ****\r\n\r\n" + msg);
                        }
                    });
                }
            });
            subcribeResource.start();
            
            subcribeResource = new SubscribeResource("eat");
            subcribeResource.setReceiver(new IReceived() {
                public void getResponseBody(final String msg) {
                    handler.post(new Runnable() {
                        public void run() {
                            textViewData.setText("**** Subscription Resource Creation Response ****\r\n\r\n" + msg);
                        }
                    });
                }
            });
            subcribeResource.start();
            
            subcribeResource = new SubscribeResource("alert");
            subcribeResource.setReceiver(new IReceived() {
                public void getResponseBody(final String msg) {
                    handler.post(new Runnable() {
                        public void run() {
                            textViewData.setText("**** Subscription Resource Creation Response ****\r\n\r\n" + msg);
                        }
                    });
                }
            });
            subcribeResource.start();
            
            subcribeResource = new SubscribeResource("success");
            subcribeResource.setReceiver(new IReceived() {
                public void getResponseBody(final String msg) {
                    handler.post(new Runnable() {
                        public void run() {
                            textViewData.setText("**** Subscription Resource Creation Response ****\r\n\r\n" + msg);
                        }
                    });
                }
            });
            subcribeResource.start();

            /* MQTT Subscribe */
            mqttClient = new MqttAndroidClient(this.getApplicationContext(), "tcp://" + csebase.getHost() + ":" + csebase.getMQTTPort(), MqttClient.generateClientId());
            mqttClient.setCallback(mainMqttCallback);
            try {
                // added by J. Yun, SCH Univ.
                // Modified by S. Lee, SCH Univ.
                MqttConnectOptions mqttConnectOptions = new MqttConnectOptions();
                mqttConnectOptions.setKeepAliveInterval(600);
                mqttConnectOptions.setCleanSession(false);

                IMqttToken token = mqttClient.connect(mqttConnectOptions);
                token.setActionCallback(mainIMqttActionListener);
            } catch (MqttException e) {
                e.printStackTrace();
            }
        } else {
            /* MQTT unSubscribe or Client Close */
            mqttClient.setCallback(null);
            mqttClient.close();
            mqttClient = null;
        }
    }

    /* MQTT Listener */
    private IMqttActionListener mainIMqttActionListener = new IMqttActionListener() {
        @Override
        public void onSuccess(IMqttToken asyncActionToken) {
            Log.d(TAG, "onSuccess");
            String payload = "";
            int mqttQos = 1; /* 0: NO QoS, 1: No Check , 2: Each Check */

            MqttMessage message = new MqttMessage(payload.getBytes());
            try {
                mqttClient.subscribe(MQTT_Req_Topic, mqttQos);
            } catch (MqttException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
            Log.d(TAG, "onFailure");
        }
    };

    /* MQTT Broker Message Received */
    private MqttCallback mainMqttCallback = new MqttCallback() {
        @Override
        public void connectionLost(Throwable cause) {
            Log.d(TAG, "connectionLost");
        }

        @Override
        public void messageArrived(String topic, MqttMessage message) throws Exception {

            Log.d(TAG, "messageArrived");

            textViewData.setText("");
            textViewData.setText("MQTT data received\r\n\r\n" + message.toString().replaceAll(",", "\n"));
            Log.d(TAG, "Notify ResMessage:" + message.toString());

            // Added by J. Yun, SCH Univ.
            // Modified by S. Lee, SCH Univ.
            String cnt = getContainerName(message.toString());
            Log.d(TAG, "Received container name is " + cnt);
            //textViewData.setText(cnt);

            if (cnt.indexOf("eat") != -1)
            {
                if(Integer.parseInt(getContainerContentJSON(message.toString())) == 1)
                {
                    textEat.setText("Ate");
                    sendNotification_3();
                }
                else
                {
                    textEat.setText("Not");
                }

            }

            if (cnt.indexOf("success") != -1)
            {
                if(Integer.parseInt(getContainerContentJSON(message.toString())) == 1)
                {
                    textSuccess.setText("ASDFASDF");
                    sendNotification_4();

                    new Handler().postDelayed(new Runnable()
                    {
                        @Override
                        public void run()
                        {
                            btn_train.performClick();
                            btnSitdown.setChecked(false);
                            btnWait.setChecked(false);
                        }
                    }, 600);
                }
                else
                {
                    sendNotification_6();
                    btn_train.performClick();
                    btnSitdown.setChecked(false);
                    btnWait.setChecked(false);

                }

            }


            if (cnt.indexOf("alert") != -1)
            {
                if(Integer.parseInt(getContainerContentJSON(message.toString())) == 1)
                {
                    textAlert.setText("Alert!");
                    sendNotification_5();
                }
                else
                {
                    textAlert.setText("Nope Alert :)");
                }

            }

            else
                ;

            /* Json Type Response Parsing */
            String retrqi = MqttClientRequestParser.notificationJsonParse(message.toString());
            Log.d(TAG, "RQI["+ retrqi +"]");

            String responseMessage = MqttClientRequest.notificationResponse(retrqi);
            Log.d(TAG, "Recv OK ResMessage ["+responseMessage+"]");

            /* Make json for MQTT Response Message */
            MqttMessage res_message = new MqttMessage(responseMessage.getBytes());

            try {
                mqttClient.publish(MQTT_Resp_Topic, res_message);
            } catch (MqttException e) {
                e.printStackTrace();
            }
        }
        @Override
        public void deliveryComplete(IMqttDeliveryToken token) {
            Log.d(TAG, "deliveryComplete");
        }

    };

    // Added by J. Yun, SCH Univ.
    // Modified by S. Lee, SCH Univ.
    private String getContainerName(String msg) {
        String cnt = "";
        try {
            JSONObject jsonObject = new JSONObject(msg);
            cnt = jsonObject.getJSONObject("pc").
                    getJSONObject("m2m:sgn").getString("sur");
            // Log.d(TAG, "Content is " + cnt);
        } catch (JSONException e) {
            Log.e(TAG, "JSONObject error!");
        }
        return cnt;
    }

    // Added by J. Yun, SCH Univ.
    private String getContainerContentJSON(String msg) {
        String con = "";
        try {
            JSONObject jsonObject = new JSONObject(msg);
            con = jsonObject.getJSONObject("pc").
                    getJSONObject("m2m:sgn").
                    getJSONObject("nev").
                    getJSONObject("rep").
                    getJSONObject("m2m:cin").
                    getString("con");
//            Log.d(TAG, "Content is " + con);
        } catch (JSONException e) {
            Log.e(TAG, "JSONObject error!");
        }
        return con;
    }

    // Added by J. Yun, SCH Univ.
    private String getContainerContentXML(String msg) {
        String con = "";
        try {
            XmlToJson xmlToJson = new XmlToJson.Builder(msg).build();
            JSONObject jsonObject = xmlToJson.toJson();
            con = jsonObject.getJSONObject("m2m:cin").getString("con");
//            Log.d(TAG, "Content is " + con);
        } catch (JSONException e) {
            Log.e(TAG, "JSONObject error!");
        }
        return con;
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {

            case R.id.btnSitdown: {
                if (((ToggleButton) v).isChecked()) {

                    btnSitdown.setVisibility(View.VISIBLE);
                    btnWait.setVisibility(View.INVISIBLE);
                    ControlRequest req = new ControlRequest("1");
                    req.setReceiver(new IReceived() {
                        public void getResponseBody(final String msg) {
                            handler.post(new Runnable() {
                                public void run() {
                                    textViewData.setText(msg);
                                }
                            });
                        }
                    });
                    req.start();
                }
                else
                {
                    btnSitdown.setVisibility(View.VISIBLE);
                    btnWait.setVisibility(View.VISIBLE);

                }

                break;
            }


            case R.id.btnWait: {

                if (((ToggleButton) v).isChecked()) {

                    btnSitdown.setVisibility(View.INVISIBLE);
                    btnWait.setVisibility(View.VISIBLE);
                    ControlRequest req = new ControlRequest("2");
                    req.setReceiver(new IReceived() {
                        public void getResponseBody(final String msg) {
                            handler.post(new Runnable() {
                                public void run() {
                                    textViewData.setText(msg);
                                }
                            });
                        }
                    });
                    req.start();
                }
                else
                {
                    btnSitdown.setVisibility(View.VISIBLE);
                    btnWait.setVisibility(View.VISIBLE);

                }

                break;
            }


            case R.id.btnVideo:
                // for URL
                Intent intent = new Intent(Intent.ACTION_VIEW,Uri.parse("http://wnsgml4.ddns.net:8081"));
//                Intent intent = new Intent(Intent.ACTION_VIEW,Uri.parse("http://google.com"));
                startActivity(intent);
                break;

            case R.id.btnRetrieve: {
                RetrieveRequest

                //MQTT
                req = new RetrieveRequest("success");
                req.setReceiver(new IReceived() {
                    public void getResponseBody(final String msg) {
                        handler.post(new Runnable() {
                            public void run() {
                                if(Integer.parseInt(getContainerContentXML(msg)) == 1)
                                {
                                    textSuccess.setText("YES");
                                    new Handler().postDelayed(new Runnable()
                                    {
                                        @Override
                                        public void run()
                                        {
                                            btn_train.performClick();
                                            btnSitdown.setChecked(false);
                                            btnWait.setChecked(false);

                                        }
                                    }, 600);
                                }
                                else
                                    textSuccess.setText("NO");
                            }
                        });
                    }
                });
                req.start();


                req = new RetrieveRequest("eat");
                req.setReceiver(new IReceived() {
                    public void getResponseBody(final String msg) {
                        handler.post(new Runnable() {
                            public void run() {
                                if(Integer.parseInt(getContainerContentXML(msg)) == 1)
                                {
                                    textEat.setText("Ate");
                                    sendNotification_3();
                                }
                                else
                                    textEat.setText("Not");
                            }
                        });
                    }
                });
                req.start();


                req = new RetrieveRequest("alert");
                req.setReceiver(new IReceived() {
                    public void getResponseBody(final String msg) {
                        handler.post(new Runnable() {
                            public void run() {
                                if(Integer.parseInt(getContainerContentXML(msg)) == 1)
                                {
                                    textAlert.setText("Alert!");
                                    sendNotification_5();
                                }
                                else
                                    textAlert.setText("Nope Alert :)");
                            }
                        });
                    }
                });
                req.start();

                req = new RetrieveRequest("remains");
                req.setReceiver(new IReceived() {
                    public void getResponseBody(final String msg) {
                        handler.post(new Runnable() {
                            public void run() {

                                textRemains.setText(getContainerContentXML(msg)+"%");
                                switch (getContainerContentXML(msg)) {
                                    case "0":
                                    case "1":
                                    case "2":
                                    case "3":
                                    case "4":
                                    case "5":
                                    case "6":
                                    case "7":
                                    case "8":
                                    case "9":
                                    case "10":
                                    case "11":
                                    case "12":
                                    case "13":
                                    case "14":
                                    case "15":
                                    case "16":
                                    case "17":
                                    case "18":
                                    case "19":
                                    case "20":
                                    case "21":
                                    case "22":
                                    case "23":
                                    case "24":
                                    case "25":
                                    case "26":
                                    case "27":
                                    case "28":
                                    case "29":
                                    case "30":
                                    case "31":
                                    case "32":
                                    case "33":
                                        sendNotification_2();
                                        break;
                                    case "34":
                                    case "35":
                                    case "36":
                                    case "37":
                                    case "38":
                                    case "39":
                                    case "40":
                                    case "41":
                                    case "42":
                                    case "43":
                                    case "44":
                                    case "45":
                                    case "46":
                                    case "47":
                                    case "48":
                                    case "49":
                                    case "50":
                                    case "51":
                                    case "52":
                                    case "53":
                                    case "54":
                                    case "55":
                                    case "56":
                                    case "57":
                                    case "58":
                                    case "59":
                                    case "60":
                                    case "61":
                                    case "62":
                                    case "63":
                                    case "64":
                                    case "65":
                                    case "66":
                                        sendNotification_1();
                                        break;
                                    default:
                                        break;
                                }

                            }
                        });
                    }
                });
                req.start();



                break;
            }

            case R.id.btn_train: {
                if (((ToggleButton) v).isChecked()) {

                    btnSitdown.setVisibility(View.VISIBLE);
                    btnWait.setVisibility(View.VISIBLE);
                    ControlRequest req = new ControlRequest("0");
                    req.setReceiver(new IReceived() {
                        public void getResponseBody(final String msg) {
                            handler.post(new Runnable() {
                                public void run() {
                                    textViewData.setText(msg);
                                }
                            });
                        }
                    });
                    req.start();
                }
                else
                {
                    btnSitdown.setVisibility(View.VISIBLE);
                    btnWait.setVisibility(View.VISIBLE);
                    ControlRequest req = new ControlRequest("0");
                    req.setReceiver(new IReceived() {
                        public void getResponseBody(final String msg) {
                            handler.post(new Runnable() {
                                public void run() {
                                    textViewData.setText(msg);
                                }
                            });
                        }
                    });
                    req.start();
                }

                break;
            }

            case R.id.toggleButton_Addr: {

                    btnRetrieve.setVisibility(View.VISIBLE);
                    Switch_MQTT.setVisibility(View.VISIBLE);

                    EditText_Address.setHintTextColor(Color.BLUE);
                    EditText_Address.setBackgroundColor(Color.LTGRAY);
                    EditText_Address.setFocusable(false);

                    InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
                    imm.hideSoftInputFromWindow(EditText_Address.getWindowToken(), 0);//hide keyboard

                    GetAEInfo();

                break;
            }


        }
    }
    @Override
    public void onStart() {
        super.onStart();

    }
    @Override
    public void onStop() {
        super.onStop();

    }

    /* Response callback Interface */
    public interface IReceived {
        void getResponseBody(String msg);
    }

    // Retrieve , added by J. Yun, SCH Univ, Modified by S. Lee, SCH Univ.
    class RetrieveRequest extends Thread {
        private final Logger LOG = Logger.getLogger(RetrieveRequest.class.getName());
        private IReceived receiver;
        //        private String ContainerName = "cnt-co2";
        private String ContainerName = "";


        public RetrieveRequest(String containerName) {
            this.ContainerName = containerName;
        }
        public RetrieveRequest() {}
        public void setReceiver(IReceived hanlder) { this.receiver = hanlder; }

        @Override
        public void run() {
            try {
                String sb = csebase.getServiceUrl() + "/" + ServiceAEName + "/" + ContainerName + "/" + "latest";

                URL mUrl = new URL(sb);

                HttpURLConnection conn = (HttpURLConnection) mUrl.openConnection();
                conn.setRequestMethod("GET");
                conn.setDoInput(true);
                conn.setDoOutput(false);

                conn.setRequestProperty("Accept", "application/xml");
                conn.setRequestProperty("X-M2M-RI", "12345");
                conn.setRequestProperty("X-M2M-Origin", ae.getAEid() );
                conn.setRequestProperty("nmtype", "long");
                conn.connect();

                String strResp = "";
                BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));

                String strLine= "";
                while ((strLine = in.readLine()) != null) {
                    strResp += strLine;
                }

                if ( strResp != "" ) {
                    receiver.getResponseBody(strResp);
                }
                conn.disconnect();

            } catch (Exception exp) {
                LOG.log(Level.WARNING, exp.getMessage());
            }
        }
    }

    /* Request Control train */
    class ControlRequest extends Thread {
        private final Logger LOG = Logger.getLogger(ControlRequest.class.getName());
        private IReceived receiver;
        private String container_name = "training";


        public ContentInstanceObject contentinstance;
        public ControlRequest(String comm) {
            contentinstance = new ContentInstanceObject();
            contentinstance.setContent(comm);
        }
        public void setReceiver(IReceived hanlder) { this.receiver = hanlder; }

        @Override
        public void run() {
            try {
                String sb = csebase.getServiceUrl() +"/" + ServiceAEName + "/" + container_name;

                URL mUrl = new URL(sb);

                HttpURLConnection conn = (HttpURLConnection) mUrl.openConnection();
                conn.setRequestMethod("POST");
                conn.setDoInput(true);
                conn.setDoOutput(true);
                conn.setUseCaches(false);
                conn.setInstanceFollowRedirects(false);

                conn.setRequestProperty("Accept", "application/xml");
                conn.setRequestProperty("Content-Type", "application/vnd.onem2m-res+xml;ty=4");
                conn.setRequestProperty("locale", "ko");
                conn.setRequestProperty("X-M2M-RI", "12345");
                conn.setRequestProperty("X-M2M-Origin", ae.getAEid() );

                String reqContent = contentinstance.makeXML();
                conn.setRequestProperty("Content-Length", String.valueOf(reqContent.length()));

                DataOutputStream dos = new DataOutputStream(conn.getOutputStream());
                dos.write(reqContent.getBytes());
                dos.flush();
                dos.close();

                BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));

                String resp = "";
                String strLine="";
                while ((strLine = in.readLine()) != null) {
                    resp += strLine;
                }
                if (resp != "") {
                    receiver.getResponseBody(resp);
                }
                conn.disconnect();

            } catch (Exception exp) {
                LOG.log(Level.SEVERE, exp.getMessage());
            }
        }
    }
    /* Request AE Creation */
    class aeCreateRequest extends Thread {
        private final Logger LOG = Logger.getLogger(aeCreateRequest.class.getName());
        String TAG = aeCreateRequest.class.getName();
        private IReceived receiver;
        int responseCode=0;
        public ApplicationEntityObject applicationEntity;
        public void setReceiver(IReceived hanlder) { this.receiver = hanlder; }
        public aeCreateRequest(){
            applicationEntity = new ApplicationEntityObject();
            applicationEntity.setResourceName(ae.getappName());
            Log.d(TAG, ae.getappName() + "JJjj");
        }
        @Override
        public void run() {
            try {

                String sb = csebase.getServiceUrl();
                URL mUrl = new URL(sb);

                HttpURLConnection conn = (HttpURLConnection) mUrl.openConnection();
                conn.setRequestMethod("POST");
                conn.setDoInput(true);
                conn.setDoOutput(true);
                conn.setUseCaches(false);
                conn.setInstanceFollowRedirects(false);

                conn.setRequestProperty("Content-Type", "application/vnd.onem2m-res+xml;ty=2");
                conn.setRequestProperty("Accept", "application/xml");
                conn.setRequestProperty("locale", "ko");
                conn.setRequestProperty("X-M2M-Origin", "S"+ae.getappName());
                conn.setRequestProperty("X-M2M-RI", "12345");
                conn.setRequestProperty("X-M2M-NM", ae.getappName() );

                String reqXml = applicationEntity.makeXML();
                conn.setRequestProperty("Content-Length", String.valueOf(reqXml.length()));

                DataOutputStream dos = new DataOutputStream(conn.getOutputStream());
                dos.write(reqXml.getBytes());
                dos.flush();
                dos.close();

                responseCode = conn.getResponseCode();

                BufferedReader in = null;
                String aei = "";
                if (responseCode == 201) {
                    // Get AEID from Response Data
                    in = new BufferedReader(new InputStreamReader(conn.getInputStream()));

                    String resp = "";
                    String strLine;
                    while ((strLine = in.readLine()) != null) {
                        resp += strLine;
                    }

                    ParseElementXml pxml = new ParseElementXml();
...

This file has been truncated, please download it to see its full contents.

Android strings.xml for Mobius App

XML
strings.xml

This file contains text information necessary to run the app.
<resources>
    <string name="app_name">WALWAL: Pet care for everyone</string>
    <string name="textview_about">WALWAL: Pet care for everyone</string>
    <string name="btn_retrieve">Reload</string>
    <string name="title">WALWAL</string>
    <string name="btn_switch">Automatic\nreceiving</string>

    <string name="mobius_address">203.253.128.177</string>
    <string name="addr_unset">Disconnected</string>
    <string name="addr_set">Connecting</string>

    <!-- Added by LSC  -->
    <string name="textview_train_label">Training</string>
    <string name="textview_train_value">Training</string>
    <string name="textview_remains_label">Remains</string>
    <string name="textview_remains_value">"?%</string>
    <string name="textview_eat_label">Food</string>
    <string name="textview_eat_value">...</string>
    <string name="textview_alert_label">alert</string>
    <string name="textview_alert_value">alert</string>

    <string name="textview_success_label">SUCCESS</string>
    <string name="textview_success_value">SUCCESS</string>

    <string name="btn_train"></string>
    <string name="btn_Sitdown"></string>
    <string name="btn_Wait"></string>


</resources>

Android activity_main.xml for Mobius App

XML
activity_main.xml

activity_main.xml is a file dedicated to the layout of the app, that is, the layout of the screen.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@drawable/background">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <TextView
                android:id="@+id/textViewTitle"
                android:layout_width="match_parent"
                android:layout_height="1sp"
                android:textSize="20sp" ></TextView>

        </LinearLayout>

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content">

            <EditText
                android:id="@+id/editText"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:ems="10"
                android:inputType="text"
                android:autofillHints="" tools:targetApi="o"
                android:focusable="false"
                tools:ignore="Suspicious0dp" ></EditText>

            <ToggleButton
                android:id="@+id/toggleButton_Addr"
                android:layout_marginTop="1115sp"
                android:layout_marginLeft="110dp"
                android:layout_width="0sp"
                android:layout_height="0dp"
                android:layout_weight="1"
                android:textSize="0sp" ></ToggleButton>

        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <Button
                android:id="@+id/btnVideo"
                android:layout_width="260sp"
                android:layout_height="260sp"
                android:onClick="onClick"
                android:layout_marginLeft="440sp"
                android:layout_marginTop="310sp"
                android:background="#00ff0011"
                android:text="" ></Button>
        </LinearLayout>


        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="0dp">

            <Switch
                android:id="@+id/switch_mqtt"
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:layout_weight="1"
                android:layout_marginTop="1114sp"
                android:layout_marginLeft="20sp"
                android:textSize="24sp"
                android:textColor="#000000" ></Switch>

        </LinearLayout>

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content">

            <ToggleButton
                android:id="@+id/btn_train"
                android:layout_marginTop="700sp"
                android:layout_marginLeft="100dp"
                android:layout_width="250sp"
                android:layout_height="60dp"
                android:layout_weight="1"
                android:textSize="16sp"
                android:textOff="Waiting for training"
                android:textOn="Training" ></ToggleButton>
        </LinearLayout>


        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">

            <Button
                android:id="@+id/btnRetrieve"
                android:layout_width="match_parent"
                android:layout_height="60sp"
                android:layout_weight="10"
                android:layout_marginTop="1115sp"
                android:layout_marginLeft="10sp"
                android:layout_marginRight="10sp"
                android:text="Reload"
                android:textSize="30sp" ></Button>
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">

            <ToggleButton
                android:id="@+id/btnSitdown"
                android:layout_width="match_parent"
                android:layout_height="50sp"
                android:layout_weight="0"
                android:layout_marginTop="760sp"
                android:layout_marginLeft="100sp"
                android:layout_marginRight="450sp"
                android:textSize="16sp"
                android:textOff="Sit down - Waiting"
                android:textOn="Sit down - Ongoing"
                android:text="Sitdown"></ToggleButton>
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">

            <ToggleButton
                android:id="@+id/btnWait"
                android:layout_width="match_parent"
                android:layout_height="50sp"
                android:layout_weight="0"
                android:layout_marginTop="810sp"
                android:layout_marginLeft="100sp"
                android:layout_marginRight="450sp"
                android:textSize="16sp"
                android:textOff="Wait - Waiting"
                android:textOn="Wait - Ongoing"
                android:text="Wait"></ToggleButton>

        </LinearLayout>


        <!--        DATA          -->
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="horizontal">
            <TextView
                android:layout_width="150sp"
                android:layout_height="wrap_content"
                android:textColor="@android:color/black"
                android:textSize="0sp" ></TextView>

            <TextView
                android:id="@+id/textRemains"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginLeft="25sp"
                android:layout_marginTop="420sp"
                android:textSize="70sp" ></TextView>
        </LinearLayout>
        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:orientation="horizontal">
            <TextView
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:textColor="@android:color/black"
                android:textSize="0sp" ></TextView>

            <TextView
                android:id="@+id/textSuccess"
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:layout_marginLeft="25sp"
                android:layout_marginTop="20sp"
                android:textSize="70sp" ></TextView>
        </LinearLayout>
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="horizontal">

            <TextView
                android:layout_width="100sp"
                android:layout_height="wrap_content"
                android:textColor="@android:color/black"
                android:textSize="0sp" ></TextView>

            <TextView
                android:id="@+id/textAlert"
                android:layout_width="0sp"
                android:layout_height="0sp"
                android:textSize="70sp" ></TextView>

        </LinearLayout>
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="horizontal">
            <TextView
                android:layout_width="50sp"
                android:layout_height="wrap_content"
                android:textColor="@android:color/black"
                android:textSize="0sp" ></TextView>

            <TextView
                android:id="@+id/textEat"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginLeft="440sp"
                android:layout_marginTop="720sp"
                android:textSize="100sp" ></TextView>

        </LinearLayout>

        <ScrollView
            android:id="@+id/scrollViewText"
            android:layout_width="match_parent"
            android:layout_height="0sp"
            android:layout_marginLeft="10sp"
            android:layout_marginTop="5sp"
            android:layout_marginRight="10sp"
            android:layout_weight="0.50"
            android:background="#575c72">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical"
                android:weightSum="1">

                <TextView
                    android:id="@+id/textViewData"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:textColor="#fdfcfc"
                    android:textSize="12sp" ></TextView>

            </LinearLayout>
        </ScrollView>

        <!--FOR PUSH-->
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content">

            <Button
                android:id="@+id/notify_1"
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:text="1">
            </Button>

            <Button
                android:id="@+id/notify_2"
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:text="2">
            </Button>

            <Button
                android:id="@+id/notify_3"
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:text="3">
            </Button>

            <Button
                android:id="@+id/notify_4"
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:text="4">
            </Button>

            <Button
                android:id="@+id/notify_5"
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:text="5">


            </Button>
            <Button
                android:id="@+id/notify_6"
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:text="1">
            </Button>
        </LinearLayout>

    </RelativeLayout>
</LinearLayout>

Android AndroidManifest.xml for Mobius App

XML
AndroidManifest.xml

Every app project must have an AndroidManifest.xml file (with precisely that name) at the root of the project source set. The manifest file describes essential information about your app to the Android build tools, the Android operating system, and Google Play.

I referred to the site.
https://developer.android.com/guide/topics/manifest/manifest-intro
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="sch.iot.onem2mapp">
    <uses-permission android:name="android.permission.INTERNET" ></uses-permission>
    <uses-permission android:name="android.permission.WAKE_LOCK" ></uses-permission>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" ></uses-permission>
    <uses-permission android:name="android.permission.READ_PHONE_STATE" ></uses-permission>

    <uses-permission android:name="android.permission.READ_PHONE_STATE" ></uses-permission>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity"
            tools:ignore="Instantiatable">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" ></action>

                <category android:name="android.intent.category.LAUNCHER" ></category>
            </intent-filter>
        </activity>
        <service android:name="org.eclipse.paho.android.service.MqttService" ></service>
    </application>

</manifest>

Android APP_WALWAL

The entire code for the app.

Credits

Changwon Lee
1 project • 1 follower
Yonghee Kim
0 projects • 1 follower
junheeChoi
0 projects • 1 follower
SeungMyeong Jeong
37 projects • 12 followers
Andreas Kraft
37 projects • 12 followers
IoT & connected home architect and developer. Ask me about oneM2M.
Miguel Angel Reina Ortega
38 projects • 7 followers
Laurent Velez
18 projects • 6 followers
Samir Medjiah
21 projects • 14 followers
Bob Flynn
32 projects • 16 followers
Giyeong Hong
0 projects • 1 follower
Seongchan Lee
0 projects • 1 follower
Xavier Piednoir
26 projects • 6 followers
Wonbae Son
32 projects • 5 followers
안일엽
17 projects • 1 follower

Comments