Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix issues #34 #35

Merged
merged 30 commits into from
Apr 12, 2021
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
03c1a19
new dan2 and new dai profile
JasonChenGt Feb 22, 2021
12d7f35
new dan2 and dai
JasonChenGt Feb 25, 2021
28e6460
Update context.js
JasonChenGt Mar 2, 2021
9522f2e
add new line at end of file
JasonChenGt Mar 2, 2021
1d2e18b
change module name to iottalkjs
JasonChenGt Mar 3, 2021
f5bddc5
dan: check whether the online message is published
JasonChenGt Mar 8, 2021
127de63
new Dummy Device example
JasonChenGt Mar 9, 2021
67c85c1
Update index.html
JasonChenGt Mar 9, 2021
e810755
Update index.js
JasonChenGt Mar 9, 2021
6d19044
add exceptions
JasonChenGt Mar 9, 2021
19800bf
rewrite dai
JasonChenGt Mar 10, 2021
ac1a6e9
rename dan.js
JasonChenGt Mar 16, 2021
d0a1eba
change the interval unit to seconds
JasonChenGt Mar 16, 2021
fb1ca00
change coding style
JasonChenGt Mar 17, 2021
9e8e91a
rewrite dan
JasonChenGt Mar 17, 2021
4767273
remove old version callback
JasonChenGt Mar 23, 2021
7c5372f
change register arguments
JasonChenGt Mar 28, 2021
092ccf5
change register arguments
JasonChenGt Mar 30, 2021
204fdda
check if document exists
JasonChenGt Mar 30, 2021
4622132
remove new Promise
JasonChenGt Apr 8, 2021
6366062
subscribe return Promise
JasonChenGt Apr 8, 2021
7382e93
use promise in on_connect()
JasonChenGt Apr 9, 2021
768fa7c
return reject in promise
JasonChenGt Apr 10, 2021
f6c68a9
remove disconnect info
JasonChenGt Apr 10, 2021
99237ab
use df function in df_list
JasonChenGt Apr 10, 2021
0d69e86
Dummy Device
JasonChenGt Apr 11, 2021
bc496b0
use Array.isArray in parse_df_profile()
JasonChenGt Apr 12, 2021
8e2bf31
change ida to sa
JasonChenGt Apr 12, 2021
576f495
use df_func_name() in parse_df_profile()
JasonChenGt Apr 12, 2021
afbcb08
Update index.html
JasonChenGt Apr 12, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@ before_deploy:
- export DISTDIR=/tmp/dist
- git fetch origin gh-pages:gh-pages
- git worktree add ${DISTDIR} gh-pages
- cp ./build-web/dan2-web.js ${DISTDIR}/dan2.js
- cp ./build-web/dan2-web.js ${DISTDIR}/dan2-${TRAVIS_COMMIT}.js
- cp ./build-web/iottalkjs-web.js ${DISTDIR}/iottalkjs.js
- cp ./build-web/iottalkjs-web.js ${DISTDIR}/iottalkjs-${TRAVIS_COMMIT}.js
- echo "TRAVIS_TAG = ${TRAVIS_TAG}"
- echo "TRAVIS_BRANCH = ${TRAVIS_BRANCH}"
- if [ "${TRAVIS_TAG}" ]; then
echo 'Add tags build';
cp ./build-web/dan2-web.js ${DISTDIR}/dan2-${TRAVIS_TAG}.js;
cp ./build-web/iottalkjs-web.js ${DISTDIR}/iottalkjs-${TRAVIS_TAG}.js;
fi

deploy:
Expand Down
20 changes: 20 additions & 0 deletions examples/Dummy_Device/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<!DOCTYPE html>
<html lang="en">

<head>
<title>Dummy_Device</title>
<script src="https://code.jquery.com/jquery-3.4.1.min.js"
integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"></script>
<script src="js/ida.js"></script>
JasonChenGt marked this conversation as resolved.
Show resolved Hide resolved
<script src="../../build-web/iottalkjs-web.js"></script>

</head>

<body>
<legend>Dummy_Sensor</legend>
<legend class='IDF_value'>_____________</legend>
<legend>Dummy_Control</legend>
<legend class='ODF_value'>_____________</legend>
</body>

</html>
28 changes: 28 additions & 0 deletions examples/Dummy_Device/js/ida.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
$(function () {
function Dummy_Sensor() {
var number = Math.floor((1 + Math.random()) * 0x10000);
$('.IDF_value')[0].innerText = number;
return [number];
}

function Dummy_Control(data) {
$('.ODF_value')[0].innerText = data[0];
}

var option = {
'api_url': 'https://iottalk2.tw/csm',
'device_model': 'Dummy_Device',
'device_addr': 'c96ca71c-9e48-2a23-2868-acb420a2f105',
'device_name': 'Dummy',
'persistent_binding': true,
'idf_list': [['Dummy_Sensor', ['int']]],
'odf_list': ['Dummy_Control'],
'df_function_list': [Dummy_Sensor, Dummy_Control],
'push_interval': 0,
'interval': {
'Dummy_Sensor': 1.5,
}
};

new iottalkjs.dai(option).run();
});
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
"name": "iottalk-js",
"version": "2.0.4",
"description": "IoTtalk javascript library SDK",
"main": "dan2.js",
"main": "iottalkjs.js",
"directories": {
"example": "examples"
},
"scripts": {
"start": "npx webpack -w --mode development",
"build": "npm run build:node && npm run build:web",
"build:node": "npx babel src --out-dir build-node && npx ncc build build-node/dan2.js -o build-node/dist && mv build-node/dist/index.js build-node/dist/dan2.js",
"build:node": "npx babel src --out-dir build-node && npx ncc build build-node/index.js -o build-node/dist && mv build-node/dist/index.js build-node/dist/iottalkjs.js",
"build:web": "npx webpack",
"test": "echo \"Error: no test specified\" && exit 1"
},
Expand Down
24 changes: 24 additions & 0 deletions src/context.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import ChannelPool from './channel-pool.js';

export default class {

constructor() {
this.url = null;
this.app_id = null;
this.name = null;
this.mqtt_host = null;
this.mqtt_port = null;
this.mqtt_username = null;
this.mqtt_password = null;
this.mqtt_client = null;
this.i_chans = new ChannelPool();
this.o_chans = new ChannelPool();
this.rev = null;
this.on_signal = null;
this.on_data = null;
this.on_register = null;
this.on_deregister = null;
this.on_connect = null;
this.on_disconnect = null;
}
}
206 changes: 206 additions & 0 deletions src/dai.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
import DeviceFeature from './device-feature.js';
import { Client } from './dan.js';
import { RegistrationError, ArgumentError } from './exceptions.js';

export default class {

constructor(option) {
this.api_url = option['api_url'];
this.device_model = option['device_model'];
this.device_addr = option['device_addr'];
this.device_name = option['device_name'];
this.persistent_binding = option['persistent_binding'] || false;
this.username = option['username'];
this.extra_setup_webpage = option['extra_setup_webpage'] || '';
this.device_webpage = option['device_webpage'] || '';

this.register_callback = option['register_callback'];
this.on_register = option['on_register'];
this.on_deregister = option['on_deregister'];
this.on_connect = option['on_connect'];
this.on_disconnect = option['on_disconnect'];

this.push_interval = option['push_interval'] != undefined ? option['push_interval'] : 1;
this.interval = option['interval'] || {};

this.device_features = {};
this.flags = {};

this.on_signal = this.on_signal.bind(this);
this.on_data = this.on_data.bind(this);

this.parse_df_profile(option, 'idf');
this.parse_df_profile(option, 'odf');
}

push_data(df_name) {
iblislin marked this conversation as resolved.
Show resolved Hide resolved
if (this.device_features[df_name].push_data == null)
return;
let _df_interval = this.interval[df_name] != undefined ? this.interval[df_name] : this.push_interval;
console.debug(`${df_name} : ${this.flags[df_name]} [message / ${_df_interval} s]`);
let _push_interval = setInterval(() => {
let _data = this.device_features[df_name].push_data();
if (!this.flags[df_name]) {
clearInterval(_push_interval);
return;
}
if (_data === undefined) {
return;
}
this.dan.push(df_name, _data);

}, _df_interval * 1000);
}

on_signal(signal, df_list) {
console.log(`Receive signal: ${signal}, ${df_list}`);
if ('CONNECT' == signal) {
df_list.forEach(df_name => {
if (this.flags[df_name]) {
return;
}
this.flags[df_name] = true;
this.push_data(df_name);
});
}
else if ('DISCONNECT' == signal) {
df_list.forEach(df_name => {
this.flags[df_name] = false;
});
}
else if ('SUSPEND' == signal) {
// Not use
}
else if ('RESUME' == signal) {
// Not use
}
return true;
}

on_data(df_name, data) {
try {
this.device_features[df_name].on_data(data);
} catch (err) {
console.error(err);
return false;
}
return true;
}

df_func_name(df_name) {
if (df_name.match(/-[A-Z]?(I|O)[0-9]?$/i)) {
return df_name.replace('-', '_');
}
return df_name;
}

_check_parameter() {
if (!this.api_url)
throw new RegistrationError('api_url is required.');

if (!this.device_model)
throw new RegistrationError('device_model not given.');

if (this.persistent_binding && !this.device_addr)
throw new ArgumentError('In case of `persistent_binding` set to `True`, ' +
'the `device_addr` should be set and fixed.');

if (Object.keys(this.device_features).length === 0)
throw new RegistrationError('Neither idf_list nor odf_list is empty.');
}

run() {
this._check_parameter();

this.dan = new Client();

let idf_list = [];
let odf_list = [];

for (const [df_name, df] of Object.entries(this.device_features)) {
if (df.df_type == 'idf')
idf_list.push([df_name, df.df_type]);
else
odf_list.push([df_name, df.df_type]);
}

let msg = {
'url': this.api_url,
'on_signal': this.on_signal,
'on_data': this.on_data,
'accept_protos': ['mqtt'],
'id': this.device_addr,
'idf_list': idf_list,
'odf_list': odf_list,
'name': this.device_name,
'profile': {
'model': this.device_model,
'u_name': this.username,
'extra_setup_webpage': this.extra_setup_webpage,
'device_webpage': this.device_webpage,
},
'register_callback': this.register_callback,
'on_register': this.on_register,
'on_deregister': this.on_deregister,
'on_connect': this.on_connect,
'on_disconnect': () => {
for (const key in this.flags) {
this.flags[key] = false;
}
console.debug(`on_disconnect: _flag = ${this.flags}`);
if (on_disconnect) {
return on_disconnect;
}
}
};

this.dan.register(msg);

// FIXME: window is not defined in node.js
window.onbeforeunload = function () {
try {
if (!this.persistent_binding) {
this.dan.deregister();
}
} catch (error) {
console.error(`dai process cleanup exception: ${error}`);
}
};
}

parse_df_profile(option, typ) {
for (let i = 0; i < option[`${typ}_list`].length; i++) {
JasonChenGt marked this conversation as resolved.
Show resolved Hide resolved
let df_name;
let param_type;
let on_data;
let push_data;
if (typeof option[`${typ}_list`][i] === 'string') {
df_name = option[`${typ}_list`][i];
param_type = null;
}
else if (typeof option[`${typ}_list`][i] === 'object' && option[`${typ}_list`][i].length == 2) {
JasonChenGt marked this conversation as resolved.
Show resolved Hide resolved
df_name = option[`${typ}_list`][i][0];
param_type = option[`${typ}_list`][i][1];
}
else {
throw new RegistrationError(`Invalid ${typ}_list, usage: [df_name, ...] or [[df_name, type], ...]`);
JasonChenGt marked this conversation as resolved.
Show resolved Hide resolved
}

option['df_function_list'].forEach(df_function => {
if (this.df_func_name(df_name) == df_function.name) {
on_data = push_data = df_function;
}
});

let df = new DeviceFeature({
'df_name': df_name,
'df_type': typ,
'param_type': param_type,
'push_data': push_data,
'on_data': on_data
});

this.device_features[df_name] = df;
}
}
}
Loading