Initial commit
This commit is contained in:
commit
c310cd7943
19 changed files with 3939 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
dist/
|
2
app-side/i18n/en-US.po
Normal file
2
app-side/i18n/en-US.po
Normal file
|
@ -0,0 +1,2 @@
|
|||
msgid "example"
|
||||
msgstr "This is an example in app-side"
|
60
app-side/index.js
Normal file
60
app-side/index.js
Normal file
|
@ -0,0 +1,60 @@
|
|||
import { MessageBuilder } from "../shared/message-side";
|
||||
|
||||
const messageBuilder = new MessageBuilder();
|
||||
|
||||
async function fetchDirectory(ctx) {
|
||||
try {
|
||||
const res = await fetch({
|
||||
url: "https://directory.spaceapi.io",
|
||||
method: "GET",
|
||||
});
|
||||
const resBody =
|
||||
typeof res.body === "string" ? JSON.parse(res.body) : res.body;
|
||||
|
||||
ctx.response({
|
||||
data: { success: true, result: resBody },
|
||||
});
|
||||
} catch (error) {
|
||||
ctx.response({
|
||||
data: { success: false, result: {} },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchStatus(url, ctx) {
|
||||
try {
|
||||
const res = await fetch({
|
||||
url: url,
|
||||
method: "GET",
|
||||
});
|
||||
const resBody =
|
||||
typeof res.body === "string" ? JSON.parse(res.body) : res.body;
|
||||
|
||||
ctx.response({
|
||||
data: { success: true, result: resBody },
|
||||
});
|
||||
} catch (error) {
|
||||
ctx.response({
|
||||
data: { success: false, result: {} },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
AppSideService({
|
||||
onInit() {
|
||||
messageBuilder.listen(() => {});
|
||||
|
||||
messageBuilder.on("request", (ctx) => {
|
||||
const jsonRpc = messageBuilder.buf2Json(ctx.request.payload);
|
||||
if (jsonRpc.method === "GET_DIRECTORY") {
|
||||
return fetchDirectory(ctx);
|
||||
} else if (jsonRpc.method === "GET_STATUS") {
|
||||
return fetchStatus(jsonRpc.url, ctx);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
onRun() {},
|
||||
|
||||
onDestroy() {},
|
||||
});
|
28
app.js
Normal file
28
app.js
Normal file
|
@ -0,0 +1,28 @@
|
|||
import "./shared/device-polyfill";
|
||||
import { MessageBuilder } from "./shared/message";
|
||||
import { getPackageInfo } from "@zos/app";
|
||||
import * as ble from "@zos/ble";
|
||||
|
||||
App({
|
||||
globalData: {
|
||||
messageBuilder: null,
|
||||
},
|
||||
onCreate(options) {
|
||||
console.log("app on create invoke");
|
||||
const { appId } = getPackageInfo();
|
||||
const messageBuilder = new MessageBuilder({
|
||||
appId,
|
||||
appDevicePort: 20,
|
||||
appSidePort: 0,
|
||||
ble,
|
||||
});
|
||||
this.globalData.messageBuilder = messageBuilder;
|
||||
messageBuilder.connect();
|
||||
},
|
||||
|
||||
onDestroy(options) {
|
||||
console.log("app on destroy invoke");
|
||||
this.globalData.messageBuilder &&
|
||||
this.globalData.messageBuilder.disConnect();
|
||||
},
|
||||
});
|
57
app.json
Normal file
57
app.json
Normal file
|
@ -0,0 +1,57 @@
|
|||
{
|
||||
"configVersion": "v2",
|
||||
"app": {
|
||||
"appId": 28358,
|
||||
"appName": "ZeppSpace",
|
||||
"appType": "app",
|
||||
"version": {
|
||||
"code": 1,
|
||||
"name": "1.0.1"
|
||||
},
|
||||
"icon": "icon.png",
|
||||
"vender": "pauljako",
|
||||
"description": "A ZeppOS App for SpaceAPI"
|
||||
},
|
||||
"permissions": [
|
||||
"data:os.device.info",
|
||||
"device:os.local_storage",
|
||||
"device:os.geolocation"
|
||||
],
|
||||
"runtime": {
|
||||
"apiVersion": {
|
||||
"compatible": "2.0.0",
|
||||
"target": "2.0.0",
|
||||
"minVersion": "2.0"
|
||||
}
|
||||
},
|
||||
"debug": false,
|
||||
"targets": {
|
||||
"bip5": {
|
||||
"module": {
|
||||
"page": {
|
||||
"pages": ["pages/home/index", "pages/status/index"]
|
||||
},
|
||||
"app-side": {
|
||||
"path": "app-side/index"
|
||||
}
|
||||
},
|
||||
"platforms": [
|
||||
{
|
||||
"name": "bip5",
|
||||
"deviceSource": 8454400
|
||||
},
|
||||
{
|
||||
"name": "bip5-w",
|
||||
"deviceSource": 8454401
|
||||
}
|
||||
],
|
||||
"designWidth": 380
|
||||
}
|
||||
},
|
||||
"i18n": {
|
||||
"en-US": {
|
||||
"appName": "ZeppSpace"
|
||||
}
|
||||
},
|
||||
"defaultLanguage": "en-US"
|
||||
}
|
BIN
assets/bip5/icon.png
Normal file
BIN
assets/bip5/icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.6 KiB |
2
pages/home/i18n/en-US.po
Normal file
2
pages/home/i18n/en-US.po
Normal file
|
@ -0,0 +1,2 @@
|
|||
msgid "example"
|
||||
msgstr "This is an example in device"
|
78
pages/home/index.js
Normal file
78
pages/home/index.js
Normal file
|
@ -0,0 +1,78 @@
|
|||
import {
|
||||
createWidget,
|
||||
widget,
|
||||
align,
|
||||
updateStatusBarTitle,
|
||||
event,
|
||||
} from "@zos/ui";
|
||||
import { log as Logger, px } from "@zos/utils";
|
||||
import { push } from "@zos/router";
|
||||
import {
|
||||
DEFAULT_COLOR,
|
||||
DEFAULT_COLOR_TRANSPARENT,
|
||||
} from "../../utils/config/constants";
|
||||
import { DEVICE_WIDTH } from "../../utils/config/device";
|
||||
import VisLog from "@silver-zepp/vis-log";
|
||||
const vis = new VisLog("index.js");
|
||||
|
||||
const logger = Logger.getLogger("ZeppSpace");
|
||||
const { messageBuilder } = getApp()._options.globalData;
|
||||
|
||||
let spaces = {};
|
||||
|
||||
Page({
|
||||
state: {},
|
||||
build() {
|
||||
updateStatusBarTitle("Spaces (Loading)");
|
||||
this.fetchData();
|
||||
},
|
||||
|
||||
fetchData() {
|
||||
messageBuilder
|
||||
.request({
|
||||
method: "GET_DIRECTORY",
|
||||
})
|
||||
.then((data) => {
|
||||
vis.log("data received");
|
||||
const statusSuccess = data["success"];
|
||||
if (!statusSuccess) {
|
||||
return;
|
||||
}
|
||||
|
||||
let spaceNames = Object.fromEntries(
|
||||
Object.entries(data["result"]).sort(([a], [b]) => a.localeCompare(b)),
|
||||
);
|
||||
|
||||
let yPos = 70;
|
||||
for (let key in spaceNames) {
|
||||
if (spaceNames.hasOwnProperty(key)) {
|
||||
spaces[key] = createWidget(widget.TEXT, {
|
||||
x: 0,
|
||||
y: px(yPos),
|
||||
w: px(DEVICE_WIDTH),
|
||||
h: px(50),
|
||||
align_h: align.CENTER_H,
|
||||
align_v: align.CENTER_V,
|
||||
text_size: px(32),
|
||||
color: 0xffffff,
|
||||
text: key,
|
||||
});
|
||||
|
||||
spaces[key].addEventListener(event.CLICK_UP, (info) => {
|
||||
push({
|
||||
url: "pages/status/index",
|
||||
params: {
|
||||
name: key,
|
||||
url: spaceNames[key],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
yPos += 50;
|
||||
}
|
||||
}
|
||||
|
||||
updateStatusBarTitle("Spaces");
|
||||
});
|
||||
},
|
||||
});
|
2
pages/status/i18n/en-US.po
Normal file
2
pages/status/i18n/en-US.po
Normal file
|
@ -0,0 +1,2 @@
|
|||
msgid "example"
|
||||
msgstr "This is an example in device"
|
110
pages/status/index.js
Normal file
110
pages/status/index.js
Normal file
|
@ -0,0 +1,110 @@
|
|||
import { createWidget, widget, align, updateStatusBarTitle } from "@zos/ui";
|
||||
import { log as Logger, px } from "@zos/utils";
|
||||
import { back } from "@zos/router";
|
||||
import {
|
||||
DEFAULT_COLOR,
|
||||
DEFAULT_COLOR_TRANSPARENT,
|
||||
} from "../../utils/config/constants";
|
||||
import { DEVICE_WIDTH } from "../../utils/config/device";
|
||||
import VisLog from "@silver-zepp/vis-log";
|
||||
const vis = new VisLog("index.js");
|
||||
|
||||
const logger = Logger.getLogger("ZeppSpace");
|
||||
const { messageBuilder } = getApp()._options.globalData;
|
||||
|
||||
let title = "";
|
||||
let url = "";
|
||||
|
||||
Page({
|
||||
state: {},
|
||||
onInit(params) {
|
||||
const data = JSON.parse(params);
|
||||
if (data["url"] == undefined || data["name"] == undefined) {
|
||||
back();
|
||||
return;
|
||||
}
|
||||
title = data["name"];
|
||||
url = data["url"];
|
||||
},
|
||||
build() {
|
||||
updateStatusBarTitle(title + " (Loading)");
|
||||
this.fetchData();
|
||||
},
|
||||
|
||||
fetchData() {
|
||||
messageBuilder
|
||||
.request({
|
||||
method: "GET_STATUS",
|
||||
url: url,
|
||||
})
|
||||
.then((data) => {
|
||||
const statusSuccess = data["success"];
|
||||
if (!statusSuccess) {
|
||||
return;
|
||||
}
|
||||
|
||||
let open = data["result"]["state"]["open"];
|
||||
|
||||
let openText = open ? "Yes" : "No";
|
||||
|
||||
createWidget(widget.TEXT, {
|
||||
x: 0,
|
||||
y: px(70),
|
||||
w: px(DEVICE_WIDTH),
|
||||
h: px(50),
|
||||
align_h: align.CENTER_H,
|
||||
align_v: align.CENTER_V,
|
||||
text_size: px(32),
|
||||
color: 0xffffff,
|
||||
text: "Open: " + openText,
|
||||
});
|
||||
|
||||
createWidget(widget.TEXT, {
|
||||
x: 0,
|
||||
y: px(120),
|
||||
w: px(DEVICE_WIDTH),
|
||||
h: px(50),
|
||||
align_h: align.CENTER_H,
|
||||
align_v: align.CENTER_V,
|
||||
text_size: px(32),
|
||||
color: 0xffffff,
|
||||
text:
|
||||
"Last Updated: " +
|
||||
this.convertTime(data["result"]["state"]["lastchange"]),
|
||||
});
|
||||
|
||||
updateStatusBarTitle(title);
|
||||
});
|
||||
},
|
||||
|
||||
convertTime(timestamp) {
|
||||
var a = new Date(timestamp * 1000);
|
||||
var today = new Date();
|
||||
var yesterday = new Date(Date.now() - 86400000);
|
||||
var months = [
|
||||
"Jan",
|
||||
"Feb",
|
||||
"Mar",
|
||||
"Apr",
|
||||
"May",
|
||||
"Jun",
|
||||
"Jul",
|
||||
"Aug",
|
||||
"Sep",
|
||||
"Oct",
|
||||
"Nov",
|
||||
"Dec",
|
||||
];
|
||||
var year = a.getFullYear();
|
||||
var month = months[a.getMonth()];
|
||||
var date = a.getDate();
|
||||
var hour = a.getHours() < 10 ? "0" + a.getHours() : a.getHours();
|
||||
var min = a.getMinutes() < 10 ? "0" + a.getMinutes() : a.getMinutes();
|
||||
if (a.setHours(0, 0, 0, 0) == today.setHours(0, 0, 0, 0))
|
||||
return hour + ":" + min;
|
||||
else if (a.setHours(0, 0, 0, 0) == yesterday.setHours(0, 0, 0, 0))
|
||||
return "Yesterday, " + hour + ":" + min;
|
||||
else if (year == today.getFullYear()) return date + " " + month;
|
||||
else return date + " " + month + " " + year;
|
||||
},
|
||||
});
|
67
shared/data.js
Normal file
67
shared/data.js
Normal file
|
@ -0,0 +1,67 @@
|
|||
export function json2buf(json) {
|
||||
return str2buf(json2str(json))
|
||||
}
|
||||
|
||||
export function json2bin(json) {
|
||||
return str2bin(json2str(json))
|
||||
}
|
||||
|
||||
export function len(binOrBuf) {
|
||||
return binOrBuf.byteLength
|
||||
}
|
||||
|
||||
export function buf2json(buf) {
|
||||
return str2json(buf2str(buf))
|
||||
}
|
||||
|
||||
export function str2json(str) {
|
||||
return JSON.parse(str)
|
||||
}
|
||||
|
||||
export function json2str(json) {
|
||||
return JSON.stringify(json)
|
||||
}
|
||||
|
||||
export function str2buf(str) {
|
||||
return Buffer.from(str, 'utf-8')
|
||||
}
|
||||
|
||||
export function buf2str(buf) {
|
||||
return buf.toString('utf-8')
|
||||
}
|
||||
|
||||
export function bin2buf(bin) {
|
||||
return Buffer.from(bin)
|
||||
}
|
||||
|
||||
export function buf2bin(buf) {
|
||||
return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength)
|
||||
}
|
||||
|
||||
export function buf2hex(buf) {
|
||||
return buf.toString('hex')
|
||||
}
|
||||
|
||||
export function bin2hex(bin) {
|
||||
return buf2hex(bin2buf(bin))
|
||||
}
|
||||
|
||||
export function bin2json(bin) {
|
||||
return buf2json(bin2buf(bin))
|
||||
}
|
||||
|
||||
export function bin2str(bin) {
|
||||
return buf2str(bin2buf(bin))
|
||||
}
|
||||
|
||||
export function str2bin(str) {
|
||||
return buf2bin(str2buf(str))
|
||||
}
|
||||
|
||||
export function allocOfBin(size = 0) {
|
||||
return Buffer.alloc(size).buffer
|
||||
}
|
||||
|
||||
export function allocOfBuf(size = 0) {
|
||||
return Buffer.alloc(size)
|
||||
}
|
35
shared/defer.js
Normal file
35
shared/defer.js
Normal file
|
@ -0,0 +1,35 @@
|
|||
export function Deferred() {
|
||||
const defer = {}
|
||||
|
||||
defer.promise = new Promise(function (resolve, reject) {
|
||||
defer.resolve = resolve
|
||||
defer.reject = reject
|
||||
})
|
||||
|
||||
return defer
|
||||
}
|
||||
|
||||
export function delay(ms) {
|
||||
const defer = Deferred()
|
||||
|
||||
setTimeout(defer.resolve, ms)
|
||||
|
||||
return defer.promise
|
||||
}
|
||||
|
||||
export function timeout(ms, cb) {
|
||||
const defer = Deferred()
|
||||
ms = ms || 1000
|
||||
|
||||
const wait = setTimeout(() => {
|
||||
clearTimeout(wait)
|
||||
|
||||
if (cb) {
|
||||
cb && cb(defer.resolve, defer.reject)
|
||||
} else {
|
||||
defer.reject('Timed out in ' + ms + 'ms.')
|
||||
}
|
||||
}, ms)
|
||||
|
||||
return defer.promise
|
||||
}
|
6
shared/device-polyfill.js
Normal file
6
shared/device-polyfill.js
Normal file
|
@ -0,0 +1,6 @@
|
|||
import './es6-promise'
|
||||
ES6Promise.polyfill()
|
||||
|
||||
Promise._setScheduler(function (flush) {
|
||||
flush && flush()
|
||||
})
|
1149
shared/es6-promise.js
Normal file
1149
shared/es6-promise.js
Normal file
File diff suppressed because it is too large
Load diff
42
shared/event.js
Normal file
42
shared/event.js
Normal file
|
@ -0,0 +1,42 @@
|
|||
export class EventBus {
|
||||
constructor() {
|
||||
this.map = new Map()
|
||||
}
|
||||
|
||||
on(type, cb) {
|
||||
if (this.map.has(type)) {
|
||||
this.map.get(type).push(cb)
|
||||
} else {
|
||||
this.map.set(type, [cb])
|
||||
}
|
||||
}
|
||||
|
||||
off(type, cb) {
|
||||
if (type) {
|
||||
if (cb) {
|
||||
const cbs = this.map.get(type)
|
||||
|
||||
if (!cbs) return
|
||||
const index = cbs.findIndex((i) => i === cb)
|
||||
|
||||
if (index >= 0) {
|
||||
cbs.splice(index, 1)
|
||||
}
|
||||
} else {
|
||||
this.map.delete(type)
|
||||
}
|
||||
} else {
|
||||
this.map.clear()
|
||||
}
|
||||
}
|
||||
|
||||
emit(type, ...args) {
|
||||
for (let cb of this.map.get(type) ? this.map.get(type) : []) {
|
||||
cb && cb(...args)
|
||||
}
|
||||
}
|
||||
|
||||
count(type) {
|
||||
return this.map.get(type) ? this.map.get(type).length : 0
|
||||
}
|
||||
}
|
1145
shared/message-side.js
Normal file
1145
shared/message-side.js
Normal file
File diff suppressed because it is too large
Load diff
1151
shared/message.js
Normal file
1151
shared/message.js
Normal file
File diff suppressed because it is too large
Load diff
2
utils/config/constants.js
Normal file
2
utils/config/constants.js
Normal file
|
@ -0,0 +1,2 @@
|
|||
export const DEFAULT_COLOR = 0xfc6950;
|
||||
export const DEFAULT_COLOR_TRANSPARENT = 0xfeb4a8;
|
2
utils/config/device.js
Normal file
2
utils/config/device.js
Normal file
|
@ -0,0 +1,2 @@
|
|||
import { getDeviceInfo } from "@zos/device";
|
||||
export const { width: DEVICE_WIDTH, height: DEVICE_HEIGHT } = getDeviceInfo();
|
Loading…
Add table
Add a link
Reference in a new issue