7 Star 33 Fork 5

mixly2 / mixio

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
mixio.js 150.17 KB
一键复制 编辑 原始数据 按行查看 历史
宋义深 提交于 2024-03-12 22:49 . allow-modify-mqtt-port
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401
var VERSION = "1.10.0"
// change pwd to src
if (process.argv[0].indexOf("node") != -1) {
// exec from source
process.chdir(process.argv[1].replace("mixio.js",""))
} else {
// exec from binary
if(process.platform == "win32") {
process.chdir(process.argv[0].replace("mixio.exe",""))
}
if(process.platform == "linux") {
process.chdir(process.argv[0].slice(0,process.argv[0].lastIndexOf("/")) + "/")
}
}
var spawnTime = new Date()
var logFileName = "logs/" + [
[spawnTime.getFullYear(), spawnTime.getMonth() + 1, spawnTime.getDate()].join("-"), [spawnTime.getHours() >= 10 ? spawnTime.getHours() : ("0" + spawnTime.getHours()), spawnTime.getMinutes() >= 10 ? spawnTime.getMinutes() : ("0" + spawnTime.getMinutes()), spawnTime.getSeconds() >= 10 ? spawnTime.getSeconds() : ("0" + spawnTime.getSeconds())].join("-")
].join("-") + ".log"
const { spawn, exec } = require('child_process');
var fs = require('fs-extra')
// if windows, clear C:\Users\%username%\AppData\Local\Temp\pkg
if (process.platform == "win32") {
fs.emptyDirSync(process.env.TEMP + "/pkg")
}
var express = require('express');
var session = require('express-session');
const sqlite3 = require('sqlite3').verbose();
var md5 = require('js-md5');
var ejs = require('ejs');
var bodyParser = require("body-parser");
const aedesmodule = require('aedes');
const http = require('http');
const https = require('https');
const ws = require('websocket-stream');
const jsdom = require("jsdom");
const { JSDOM } = jsdom;
var jq = require("jquery");
const mqtt = require('mqtt');
var { JSLang, arrLang, lang } = require("./js/lang.js")
const path = require('path');
var readline = require('readline');
var iconv = require('iconv-lite');
var request = require('request');
const cors = require('cors');
function init(cb){
if (!fs.existsSync("logs")) {
fs.mkdirSync("logs")
}
if (!fs.existsSync("config")) {
fs.mkdirSync("config")
var defaultConfig = `{
"MIXIO_HTTP_PORT": 8080,
"MIXIO_HTTPS_PORT": 8443,
"MIXIO_MQTT_PORT": 1883,
"MIXIO_WS_PORT": 8083,
"MIXIO_WSS_PORT": 8084,
"MAX_PROJECT_NUM_PER_USER": 20,
"MAX_MESSAGE_PER_USER": 1000,
"MAX_MESSAGE_PER_SECOND": 5,
"ALLOW_REGISTER": true,
"ALLOW_HOOK": true,
"OFFLINE_MODE": true,
"BAIDU_MAP_AK": "",
"BAIDU_MAP_SERVER_AK": "",
"ADMIN_USERNAME":"admin",
"ADMIN_PASSWORD":"public",
"STORAGE_ENGINE":"sqlite",
"MYSQL_HOST":"localhost",
"MYSQL_PORT":3306,
"MYSQL_USER":"",
"MYSQL_PASS":"",
"MYSQL_DB":"mixio",
"FOOTER":""
}`
fs.writeFileSync("config/config.json", defaultConfig)
fs.mkdirSync("config/certs")
var defaultCrt =
`-----BEGIN CERTIFICATE-----
MIICRDCCAa0CFCVQzFjsGbbYOOlCxMGn1sZyBzwVMA0GCSqGSIb3DQEBCwUAMGEx
CzAJBgNVBAYTAkNOMRAwDgYDVQQIDAdCZWlqaW5nMRAwDgYDVQQHDAdCZWlqaW5n
MQ4wDAYDVQQKDAVNaXhseTEOMAwGA1UECwwFTWl4SU8xDjAMBgNVBAMMBU1peElP
MB4XDTIyMDEyOTA4MDE0MVoXDTIzMDEyOTA4MDE0MVowYTELMAkGA1UEBhMCQ04x
EDAOBgNVBAgMB0JlaWppbmcxEDAOBgNVBAcMB0JlaWppbmcxDjAMBgNVBAoMBU1p
eGx5MQ4wDAYDVQQLDAVNaXhJTzEOMAwGA1UEAwwFTWl4SU8wgZ8wDQYJKoZIhvcN
AQEBBQADgY0AMIGJAoGBAM3xzY1n5V05vAZbYniDbMoNXCzgL5puebmV2mIkMAHv
QnhMZHv2O938ezFae0l3A6zRkhWgX4XLmGUwKria3xCC9E0soF2wM0JfIFpDIQ5g
WnixtCiI8MjV8hXQ0Nh1hJ0MMwEX6g72N/YyH5Y/P9lsmr6OiG7dXe4oyaROY/U5
AgMBAAEwDQYJKoZIhvcNAQELBQADgYEASvGJMK+h09mGCsza7h2ieVe75ogbG/nK
+c7KYYOBR2OXTNk90Od+2tJog5hJl8M1nRDHdOEPgTPDYKVz0hXjJBZnM5NtcoYS
pq6vf83MtY8polmly/EZsZqiVPaEsH97nniRoMOP4JdyKlqU2g94yFDUiTTZW4cS
iURo4pW8gRE=
-----END CERTIFICATE-----
`
fs.writeFileSync("config/certs/file.crt", defaultCrt)
var defaultPem =
`-----BEGIN PRIVATE KEY-----
MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAM3xzY1n5V05vAZb
YniDbMoNXCzgL5puebmV2mIkMAHvQnhMZHv2O938ezFae0l3A6zRkhWgX4XLmGUw
Kria3xCC9E0soF2wM0JfIFpDIQ5gWnixtCiI8MjV8hXQ0Nh1hJ0MMwEX6g72N/Yy
H5Y/P9lsmr6OiG7dXe4oyaROY/U5AgMBAAECgYB8zETFpeoF/lCEgahAY1PvdP0g
bJIsQToeTkLSKh+1bGmZQKG7xNEuiiuVEsGXGTnu5ehilpaMG340A2ZADAmTf552
Zr7AHSWmg4YEEykihSoJ2owfmqamm5Fsyoe/oxijsWwXAiZIv6VkDznchnQ+1I/w
Ioyigp+dHbHS3OjiAQJBAOaDx0XjofpJQe4oCufTIqltomRtxtP4fFbeEbmQrXRt
zNvH6QeKeanA+F4JQGVKcDSt6rz5yi8MqukOpZKBcdkCQQDktp4hfgvCQN8U50t+
izZVImXGb47tfNKCWkNdrVnMI597ad3Qx+NV41oohMV4SFNCA8VgTq2onkhBbRjP
YSJhAkBp9n2t5Nvan75M6d9JfcbbN2iE3emeGwWdMOvY72astKSNCzJVoxQWMnx5
TatqZHN7486aHAES67HM/EykMhjRAkArlooog+clzEs3pqUCpvFh5D5VRSmOJT3R
TfaMwd7dQuTAFnsJsS6oTb3+/t7Lf60uZZ2WLyh1fET1Ax+5Vh/BAkEAlNxqK/DI
Fu1JviGs33vE55YHu4F0u822PUT9XN8NNzFhsvK5Oza+O7Tyyq7WJejR7I8IjzOb
RvSzVsDN3/+4ug==
-----END PRIVATE KEY-----
`
fs.writeFileSync("config/certs/private.pem", defaultPem)
}
if (!fs.existsSync("storage")) {
fs.mkdirSync("storage")
var newDB = new sqlite3.Database("storage/mixio.db", sqlite3.OPEN_READWRITE | sqlite3.OPEN_CREATE, function(err) {
if (err) {
console.log(err)
cb(false)
}
else{
newDB.run(`CREATE TABLE "devices" (
"userName" TEXT,
"clientid" TEXT,
"timestamp" INTEGER DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY("clientid")
)`,function(err){
if(err){
console.log(err)
cb(false)
}
else
{
newDB.run(`CREATE TABLE "project" (
"projectName" TEXT,
"userName" TEXT,
"projectLayout" TEXT,
"dataStorage" TEXT,
"logicStorage" TEXT,
"timestamp" INTEGER DEFAULT CURRENT_TIMESTAMP,
"projectType" INTEGER
)`, function(err){
if(err){
console.log(err)
cb(false)
}
else
{
newDB.run(`CREATE TABLE "share" (
"shareid" TEXT,
"userName" TEXT,
"projectName" TEXT,
"projectLayout" TEXT,
"dataStorage" TEXT,
"logicStorage" TEXT,
"timeStamp" INTEGER DEFAULT CURRENT_TIMESTAMP,
"status" INTEGER DEFAULT 1,
"shareCount" INTEGER DEFAULT 0
)`, function(err){
if(err){
console.log(err)
cb(false)
}
else
{
newDB.run(`CREATE TABLE "share_key" (
"userName" TEXT,
"projectPass" TEXT,
"projectName" TEXT,
"share_key" TEXT
)`, function(err){
if(err)
{
console.log(err)
cb(false)
}
else
{
newDB.run(`CREATE TABLE "user" (
"id" INTEGER,
"username" TEXT,
"password" TEXT,
"salt" TEXT,
"is_superuser" INTEGER DEFAULT 0,
"verified" INTEGER DEFAULT 1,
"question" TEXT,
"answer" TEXT,
PRIMARY KEY("id" AUTOINCREMENT)
)`, function(err){
if(err)
{
console.log(err)
cb(false)
}
else
{
newDB.close()
fs.mkdirSync("storage/reserve")
fs.writeFileSync("storage/reserve/filter.json", "{}")
var newDB1 = new sqlite3.Database("storage/reserve/1.db", sqlite3.OPEN_READWRITE | sqlite3.OPEN_CREATE, function(err) {
if(err)
{
console.log(err)
cb(false)
}
else
{
newDB1.run(`CREATE TABLE "reserve" (
"id" INTEGER,
"userName" TEXT NOT NULL,
"topic" TEXT NOT NULL,
"message" TEXT NOT NULL,
"time" INTEGER DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY("id" AUTOINCREMENT)
)`, function(err){
if(err)
{
console.log(err)
cb(false)
}
else
{
newDB1.close()
for(var i = 2;i<=8;i = i+1){
fs.copyFileSync("storage/reserve/1.db","storage/reserve/" + i + ".db")
}
cb(true)
}
})
}
})
}
})
}
})
}
})
}
})
}
})
}
})
}
else
cb(true)
}
var mysql = require('mysql8');
var serverStatus = true
var globalWeather = {}
var globalConnectionControl = {}
stringendecoder = function() {
this.REGX_HTML_ENCODE = /"|&|'|<|>|[\x00-\x20]|[\x7F-\xFF]|[\u0100-\u2700]/g;
this.REGX_HTML_DECODE = /&\w+;|&#(\d+);/g;
this.REGX_TRIM = /(^\s*)|(\s*$)/g;
this.HTML_DECODE = {
"&lt;": "<",
"&gt;": ">",
"&amp;": "&",
"&nbsp;": " ",
"&quot;": "\"",
"&copy;": ""
};
this.encodeHtml = function(s) {
s = (s != undefined) ? s : this.toString();
return (typeof s != "string") ? s :
s.replace(this.REGX_HTML_ENCODE,
function($0) {
var c = $0.charCodeAt(0),
r = ["&#"];
c = (c == 0x20) ? 0xA0 : c;
r.push(c);
r.push(";");
return r.join("");
});
};
this.decodeHtml = function(s) {
var HTML_DECODE = this.HTML_DECODE;
s = (s != undefined) ? s : this.toString();
return (typeof s != "string") ? s :
s.replace(this.REGX_HTML_DECODE,
function($0, $1) {
var c = HTML_DECODE[$0];
if (c == undefined) {
if (!isNaN($1)) {
c = String.fromCharCode(($1 == 160) ? 32 : $1);
} else {
c = $0;
}
}
return c;
});
};
this.trim = function(s) {
s = (s != undefined) ? s : this.toString();
return (typeof s != "string") ? s :
s.replace(this.REGX_TRIM, "");
};
this.hashCode = function() {
var hash = this.__hash__,
_char;
if (hash == undefined || hash == 0) {
hash = 0;
for (var i = 0, len = this.length; i < len; i++) {
_char = this.charCodeAt(i);
hash = 31 * hash + _char;
hash = hash & hash; // Convert to 32bit integer
}
hash = hash & 0x7fffffff;
}
this.__hash__ = hash;
return this.__hash__;
};
};
stringendecoder.call(stringendecoder)
async function daemon_start() {
var app = express();
app.use(bodyParser.json({
limit: '50mb'
}));
app.use(bodyParser.urlencoded({
limit: '50mb',
extended: true
}));
app.set('trust proxy', 1)
app.use(session({
secret: 'mixio',
name: 'mixio',
resave: false,
rolling: true,
saveUninitialized: true,
cookie: {
path: '/',
httpOnly: true,
maxAge: 18000000
}
}));
app.get('/', function(req, res) {
ejs.renderFile(__dirname + '/ejs/admin.ejs', {}, function(err, data) {
res.send(data)
})
})
app.get('/queryData', function(req, res) {
var data = []
var messages = []
var cb = function(num, newFunc) {
if (num >= 1) {
var next = num - 1
reserveDBs[next].all("select userName,count(*) from `reserve` group by userName", function(err, rows) {
if (rows) {
messages.push(...rows)
}
cb(next, newFunc)
})
} else {
newFunc()
}
}
cb(8, function() {
db.all("select username from `user`", function(err, rows1) {
db.all("select userName,count(*) from `project` group by username", function(err, rows2) {
for (var i = 0; i <= rows1.length - 1; i = i + 1) {
var username = rows1[i]["username"]
var projects = 0
var msgs = 0
for (var j = 0; j <= rows2.length - 1; j = j + 1) {
if (rows2[j]["userName"] == username) {
projects = rows2[j]["count(*)"]
break
}
}
for (var j = 0; j <= messages.length - 1; j = j + 1) {
if (messages[j]["userName"] == username) {
msgs = messages[j]["count(*)"]
break
}
}
data.push({
"username": username,
"projects": projects,
"messages": msgs
})
}
res.send(data)
})
})
})
})
app.get('/admin', function(req, res) {
if (req.session.admin) {
ejs.renderFile(__dirname + '/ejs/manage.ejs', {
'configs': configs,
'status': serverStatus ? "运行中" : "已暂停",
'version': VERSION
}, function(err, data) {
res.send(data)
})
} else
res.redirect('/')
})
app.get('/clearMessage', function(req, res) {
if (req.session.admin) {
var userName = req.query.userName
if (userName) {
var hash = 0,i, chr;
for (i = 0; i < userName.length; i++) {
chr = userName.charCodeAt(i);
hash = ((hash << 5) - hash) + chr;
hash |= 0;
}
var targetDB = reserveDBs[Math.abs(hash) % 8]
targetDB.run("delete from `reserve` where userName=?", [userName, ], function(err) {
if (err) {
console.log(err.message)
res.send('-1')
} else {
res.send('1')
}
})
} else
res.send('-1')
} else
res.send('-1')
})
app.get('/clearProject', function(req, res){
if(req.session.admin){
var userName = req.query.userName
if(userName){
db.run("delete from `project` where userName=?", [userName, ], function(err){
if(err){
console.log(err.message)
res.send('-1')
}else{
res.send('1')
}
})
}else
res.send('-1')
}
})
app.get('/clearUser', function(req, res){
if(req.session.admin){
var userName = req.query.userName
if(userName){
db.run("delete from `user` where username=?", [userName, ], function(err){
if(err){
console.log(err.message)
res.send('-1')
}else{
res.send('1')
}
})
}else
res.send('-1')
}
})
app.post('/adminLogin', function(req, res) {
if (req.body.userName == (configs["ADMIN_USERNAME"] ? configs["ADMIN_USERNAME"] : "admin") && req.body.password == (configs["ADMIN_PASSWORD"] ? configs["ADMIN_PASSWORD"] : "public")) {
req.session.admin = true
res.send('1')
} else {
res.send('-1')
}
})
app.get('/saveAndRestart', async function(req, res) {
newConfig = JSON.parse(req.query.configs)
for(var key in newConfig)
configs[key] = newConfig[key]
newConfig = JSON.stringify(configs, null, 4)
if (newConfig) {
fs.writeFileSync(configPath, newConfig)
configs = JSON.parse(newConfig)
console.log("[INFO] Shutting down MixIO Server...")
await mixio.stop();
serverStatus = false;
console.log("[INFO] MixIO Server is already shut down.")
console.log("[INFO] Starting MixIO Server...")
mixio = await mixioServer();
serverStatus = true;
res.send('1')
} else
res.send('-1')
})
app.get('/stop', async function(req, res) {
if (serverStatus) {
console.log("[INFO] Shutting down MixIO Server...")
await mixio.stop();
console.log("[INFO] MixIO Server is already shut down.")
serverStatus = false
res.send('1')
} else {
res.send('-1')
}
})
app.get('/addAccount', function(req, res2) {
var userName = req.query.userName
var password = req.query.password
var question = req.query.question
var answer = req.query.answer
if (userName && password && question && answer) {
require('http').get('http://localhost:' + configs["MIXIO_HTTP_PORT"] + "/addAccount?userName=" + userName + "&password=" + password + "&question=" + question + "&answer=" + answer, function(req, res) {
var html = '';
req.on('data', function(data) {
html += data;
});
req.on('end', function() {
res2.send(html)
});
}).on('error', function() {
res2.send('3')
})
}
})
app.get('/start', async function(req, res) {
if (!serverStatus) {
console.log("[INFO] Starting MixIO Server...")
mixio = await mixioServer();
serverStatus = true
res.send('1')
} else
res.send('-1')
})
app.use('/js', express.static(path.join(__dirname, 'js')));
app.use('/css', express.static(path.join(__dirname, 'css')));
app.use('/img', express.static(path.join(__dirname, 'img')));
app.use('/fonts', express.static(path.join(__dirname, 'fonts')));
app.use('/blockly', express.static(path.join(__dirname, 'blockly')));
app.use('/icons', express.static(path.join(__dirname, 'icons')));
app.use('/documentation', express.static(path.join(__dirname, 'documentation')));
app.listen(18084, function() {
console.log("[INFO] MixIO Admin server listening on port", 18084)
})
}
var mixioServer = function() {
var keyPath = "config/certs/private.pem"
var crtPath = "config/certs/file.crt"
var privateKey = fs.readFileSync(keyPath, 'utf8');
var certificate = fs.readFileSync(crtPath, 'utf8');
var credentials = {
key: privateKey,
cert: certificate
};
var chainPath = "config/certs/chain.crt"
if(fs.existsSync(chainPath))
credentials['ca'] = fs.readFileSync(chainPath, 'utf8')
aedes = aedesmodule()
const httpServer = http.createServer()
var tasks = {};
function startHost(userName, projectName, projectPass, callback) {
db.get("select * from `project` where userName=? and projectName=?", [userName, projectName], function(err, row) {
if (row) {
var projectLayout = row["projectLayout"]
var dataStorage = row["dataStorage"]
if (dataStorage == null)
dataStorage = "{}"
var logicStorage = row["logicStorage"]
var code = ""
var dom = ""
try {
if (projectLayout != null) {
var layoutJSON = JSON.parse(projectLayout)["layout_info"]
if (layoutJSON && layoutJSON != [])
dom = stringendecoder.decodeHtml(layoutJSON)
}
if (logicStorage != null)
code = stringendecoder.decodeHtml(JSON.parse(logicStorage)["code"])
else
code = ""
} catch {
}
var illegalKeywords = ["for", "while"]
var isIllegal = false
for (wordIndex in illegalKeywords) {
if (code.indexOf(illegalKeywords[wordIndex]) != -1) {
isIllegal = true
break
}
}
if (isIllegal) {
callback(JSON.stringify({
"code": -3
}))
return
}
var codeFunction = function(obj) {
return Function("return(" + obj + ")")()(
new MixIOclosure(userName, projectName, projectPass, dataStorage, dom)
)
}
try {
var closure = codeFunction("function(MixIO){ " + code + " return MixIO}")
if (tasks[userName])
tasks[userName].push({
'projectName': projectName,
'projectPass': projectPass,
'closure': closure
})
else
tasks[userName] = [{
'projectName': projectName,
'projectPass': projectPass,
'closure': closure
}]
//Normal start
callback(JSON.stringify({
"code": 1
}))
} catch (e) {
console.log(e)
//Exception
callback(JSON.stringify({
"code": -1,
"exception": e
}))
}
} else {
//Project Not Found
callback(JSON.stringify({
"code": -2
}))
}
})
}
function endHost(userName, projectName, callback) {
if (tasks[userName]) {
for (userTask in tasks[userName]) {
if (tasks[userName][userTask]["projectName"] == projectName) {
tasks[userName][userTask]["closure"].stop_project()
tasks[userName].splice(userTask, 1);
callback()
break
}
}
}
}
function randomString(length, chars) {
var result = '';
for (var i = length; i > 0; --i) result += chars[Math.floor(Math.random() * chars.length)];
return result;
}
ws.createServer({
server: httpServer
}, aedes.handle)
const plainServer = require('net').createServer(aedes.handle)
const httpsServer = https.createServer(credentials)
ws.createServer({
server: httpsServer
}, aedes.handle)
aedes.authenticate = function(client, username, password, callback) {
if (username == "MixIO_public" && password == "MixIO_public") {
client.user = "MixIO"
callback(null, true)
} else
db.get("select password from user where username = ?", [username], function(err, row) {
var auth = false
if (err)
console.log(err)
else if (row && (row["password"] == password)) {
auth = true
client.user = username
}
callback(null, auth)
})
}
aedes.authorizePublish = function(client, packet, callback) {
if(packet.topic=="$SYS/hello")
return callback(null)
if (client.user != packet.topic.split('/')[0])
return callback(new Error('wrong topic'))
else
{
if(globalConnectionControl[client.id])
{
if(Date.now() - globalConnectionControl[client.id][0] > 1000)
{
globalConnectionControl[client.id][0] = Date.now()
globalConnectionControl[client.id][1] = 0
}
else if(globalConnectionControl[client.id][1] > MAX_MESSAGE_PER_SECOND)
{
delete globalConnectionControl[client.id]
return callback(new Error('too fast'))
}
}
callback(null)
}
}
aedes.authorizeSubscribe = function(client, subscription, callback) {
if (client.user != subscription.topic.split('/')[0] && subscription.topic!="$SYS/hello")
return callback(new Error('wrong topic'))
else
callback(null, subscription);
}
setInterval(function(){
aedes.publish({
cmd: 'publish',
qos: 0,
dup: false,
topic: '$SYS/hello',
payload: Buffer.from(""+Date.now()),
retain: false
})
},10000)
aedes.on('publish', function(packet, client) {
if(client)
{
if(globalConnectionControl[client.id])
globalConnectionControl[client.id][1] = globalConnectionControl[client.id][1] + 1
else
globalConnectionControl[client.id] = [Date.now(),1]
}
var topic = packet.topic.split('/')
var payload = String(packet.payload)
if (topic.length == 3) {
if (topic[2] == 'b640a0ce465fa2a4150c36b305c1c11b') {
if(STORAGE_ENGINE == "sqlite")
db.run("insert or ignore into devices (userName, clientid) values (?,?)", [topic[0], payload])
else if(STORAGE_ENGINE == "mysql")
db.run("insert ignore into devices (userName, clientid) values (?,?)", [topic[0], payload])
} else if (topic[2] == '9d634e1a156dc0c1611eb4c3cff57276') {
db.run("delete from devices where userName = ? and clientid = ?", [topic[0], payload])
if(client)
delete globalConnectionControl[client.id]
} else if (configs["ALLOW_HOOK"] && reserveJSON[topic[0]] && topic[0] != "$SYS") {
var userName = topic[0]
var reserveTopic = topic[1] + "/" + topic[2]
var hash = 0,i, chr;
for (i = 0; i < userName.length; i++) {
chr = userName.charCodeAt(i);
hash = ((hash << 5) - hash) + chr;
hash |= 0;
}
var targetDB = reserveDBs[Math.abs(hash) % 8]
targetDB.get("select count(*) from `reserve` where userName = ?", [userName, ], function(err, row) {
if (err) {
console.log(err.message)
} else {
if (row && row["count(*)"] < MAX_MESSAGE_PER_USER) {
targetDB.run("insert into `reserve` (userName, topic, message) values (?,?,?)", [userName, reserveTopic, payload], function(err) {
if (err) {
console.log(err.message)
}
})
} else if (row["count(*)"] >= MAX_MESSAGE_PER_USER) {
targetDB.get("select id from `reserve` where userName = ? order by id asc limit 1", [userName, ], function(err, row) {
if (err) {
console.log(err.message)
} else {
if (row && row["id"]) {
targetDB.run("delete from `reserve` where id = ?", [row["id"], ], function(err) {
if (err) {
console.log(err.message)
}
else{
targetDB.run("insert into `reserve` (userName, topic, message) values (?,?,?)", [userName, reserveTopic, payload], function(err) {
if (err) {
console.log(err.message)
}
})
}
})
}
}
})
}
}
})
}
}
})
var app = express();
app.use(bodyParser.json({
limit: '50mb'
}));
app.use(bodyParser.urlencoded({
limit: '50mb',
extended: true
}));
app.use(session({
secret: 'mixio',
name: 'mixio',
resave: false,
rolling: true,
saveUninitialized: true,
cookie: {
path: '/',
httpOnly: true,
maxAge: 18000000
}
}));
app.set('trust proxy', 1)
app.use(cors())
app.get('/', function(req, res) {
ejs.renderFile(__dirname + '/ejs/index.ejs', {
'footer':configs["FOOTER"],
'mixly':fs.existsSync("../mixly")
}, function(err, data) {
res.send(data)
})
})
app.post('/proxy', function(req, res) {
var url = req.body.url
var data = req.body.data
// timeout in 5 seconds
var timeout = 50000
request({
url: url,
method: "POST",
json: true,
headers: {
"content-type": "application/json",
},
body: data,
timeout: timeout
}, function(error, response, body) {
if (!error) {
res.send(body)
} else {
res.send({
"status": "failed",
"reason": error
})
}
}
)
})
app.get('/index', function(req, res) {
ejs.renderFile(__dirname + '/ejs/index.ejs', {
'main':fs.existsSync("config/certs/chain.crt"),
'mixly':fs.existsSync("../mixly")
}, function(err, data) {
res.send(data)
})
})
app.get('/observe', function(req, res) {
ejs.renderFile(__dirname + '/ejs/observe.ejs', {
'configs': configs
}, function(err, data) {
res.send(data)
})
})
app.get('/host', function(req, res) {
ejs.renderFile(__dirname + '/ejs/host.ejs', {
'configs': configs
}, function(err, data) {
res.send(data)
})
})
app.get('/webapps', function(req, res) {
if (req.session.userName) {
db.all("select * from `share` where userName=?", [req.session.userName], function(err, rows) {
if (err)
console.log(err)
else
{
for(i in rows){
var tmp = new Date(new Date(rows[i]['timeStamp']).getTime() + 28800000)
rows[i]['timeStamp'] = ""+tmp.getFullYear()+"-"
if(tmp.getMonth()<9)
rows[i]['timeStamp'] += "0"
rows[i]['timeStamp'] += (tmp.getMonth()+1)+"-"
if(tmp.getDate()<10)
rows[i]['timeStamp'] += "0"
rows[i]['timeStamp'] += tmp.getDate()+" "
if(tmp.getHours()<10)
rows[i]['timeStamp'] += "0"
rows[i]['timeStamp'] += tmp.getHours()+":"
if(tmp.getMinutes()<10)
rows[i]['timeStamp'] += "0"
rows[i]['timeStamp'] += tmp.getMinutes()+":"
if(tmp.getSeconds()<10)
rows[i]['timeStamp'] += "0"
rows[i]['timeStamp'] += tmp.getSeconds()
}
ejs.renderFile(__dirname + '/ejs/apps.ejs', {
'rows': rows
}, function(err, data) {
res.send(data)
})
}
})
} else
res.redirect('/')
})
app.get('/register', function(req, res) {
if (configs["ALLOW_REGISTER"])
res.sendFile(__dirname + "/" + "ejs/register.html");
else
res.send('不允许自助注册!')
})
app.get('/forgot', function(req, res) {
res.sendFile(__dirname + "/" + "ejs/forgot-password.html");
})
app.get('/verify', function(req, res) {
if (req.session.userName && req.session.salt) {
ejs.renderFile(__dirname + '/ejs/verify.ejs', {
userName: req.session.userName
}, function(err, data) {
res.send(data)
})
} else
res.redirect('/')
})
app.get('/android', function(req, res) {
res.download(__dirname + "/" + "ejs/MixIO.apk")
})
app.get('/fetchObserve', function(req, res) {
if (req.query.sid) {
var sid = req.query.sid
db.get("select * from `share` where shareid=?", [sid], function(err, row) {
if (err) {
console.log(err)
res.send('-1')
} else {
if (row && row["status"] == 1) {
var userName = row["userName"]
db.get("select * from `user` where username =?", [userName], function(err, row2) {
if (err) {
console.log(err)
res.send('-1')
} else if (row2) {
row["projectPass"] = row2["password"]
res.send(JSON.stringify(row))
} else
res.send('-1')
})
} else
res.send('-1')
}
})
} else
res.send('-1')
})
app.get('/reset', function(req, res) {
if (req.query.target && req.query.vfcode && req.query.pass) {
db.get("select * from `user` where username=?", [req.query.target], function(err, row) {
if (err)
console.log(err)
else
if (row) {
if (row["answer"] == req.query.vfcode) {
var salt = randomString(16, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
var password = md5(req.query.pass + salt)
db.run("update `user` set password = ?,salt = ? where username=?", [password, salt, req.query.target], function(err) {
if (err)
console.log(err)
else
res.send('1')
})
} else
res.send('2')
} else
res.send('2')
})
} else
res.send('2')
})
app.get('/setProtect', function(req, res) {
if (req.session.userName && req.query.question && req.query.answer) {
db.run("update `user` set question=? , answer=? , verified=1 where username=?", [req.query.question, req.query.answer, req.session.userName], function(err) {
if (err)
console.log(err)
else
res.send('1')
})
} else
res.redirect('/')
})
app.get('/registerAccount', function(req, res) {
if (req.query.userName && req.query.password) {
db.get("select * from `user` where username=?", [req.query.userName], function(err, row) {
if (err)
console.log(err)
else {
if (row) {
if (req.session.salt)
req.session.salt = undefined
res.send('2')
} else {
var salt = randomString(16, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
req.session.userName = req.query.userName
req.session.salt = salt
var password = md5(req.query.password + salt)
db.run("insert into `user` (username, password, salt, verified, question, answer) values(?,?,?,0, '', '')", [req.query.userName, password, salt], function(err) {
if (err)
console.log(err)
else
res.send('1')
})
}
}
})
}
})
app.get('/addAccount', function(req, res) {
if (req.query.userName && req.query.password && req.query.question && req.query.answer) {
db.get("select * from `user` where username=?", [req.query.userName], function(err, row) {
if (err)
console.log(err)
else {
if (row) {
if (req.session.salt)
req.session.salt = undefined
res.send('2')
} else {
var salt = randomString(16, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
req.session.userName = req.query.userName
req.session.salt = salt
var password = md5(req.query.password + salt)
db.run("insert into `user` (username, password, salt, verified, question, answer) values(?,?,?,1,?,?)", [req.query.userName, password, salt, req.query.question, req.query.answer], function(err) {
if (err)
console.log(err)
else
res.send('1')
})
}
}
})
}
})
app.post('/addAccount', function(req, res) {
if (req.body.userName && req.body.password) {
db.get("select * from `user` where username=?", [req.body.userName], function(err, row) {
if (err)
res.send("Internal Error", 500)
else {
if (row) {
res.send({
"status": "failed",
"reason": "user already exists"
})
} else {
var question = req.body.question ? req.body.question : ""
var answer = req.body.answer ? req.body.answer : ""
var salt = randomString(16, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
var password = md5(req.body.password + salt)
db.run("insert into `user` (username, password, salt, verified, question, answer) values(?,?,?,1,?,?)", [req.body.userName, password, salt, question, answer], function(err) {
if (err)
res.send("Internal Error", 500)
else
res.send({
"status": "success"
})
})
}
}
})
}
else
res.send({
"status": "failed",
"reason": "bad request"
})
})
app.post('/resetPassword', function(req, res) {
if (req.body.userName && req.body.oldPassword && req.body.newPassword) {
db.get("select * from `user` where username=?", [req.body.userName], function(err, row) {
if (err)
res.send("Internal Error", 500)
else {
if (row) {
if(row["password"] == md5(req.body.oldPassword + row["salt"]))
{
var salt = randomString(16, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
var password = md5(req.body.newPassword + salt)
db.run("update `user` set password=?,salt=? where username=?", [password, salt, req.body.userName], function(err) {
if (err)
res.send("Internal Error", 500)
else
res.send({
"status": "success"
})
})
}
else
res.send({
"status": "failed",
"reason": "wrong password"
})
} else {
res.send({
"status": "failed",
"reason": "user not found"
})
}
}
})
}
else
res.send({
"status": "failed",
"reason": "bad request"
})
})
app.get('/getDevices', function(req, res) {
if (req.session.userName && req.query.userName) {
var userName = req.query.userName
db.all("select clientid from devices where userName = ?", [userName], function(err, rows) {
res.send(JSON.stringify(rows))
})
} else
res.redirect('/')
})
app.get('/projects', function(req, res) {
if (req.session.userName) {
ejs.renderFile(__dirname + '/ejs/projects.ejs', {
isMixly: 0,
userName: req.session.userName,
projectPass: req.session.projectPass,
prjid: req.query.prjid ? req.query.prjid : 'no',
'configs': configs
}, function(err, data) {
res.send(data)
})
} else
res.redirect('/')
})
app.get('/mqttdata', function(req, res) {
if (req.session.userName) {
ejs.renderFile(__dirname + '/ejs/data.ejs', {
userName: req.session.userName,
projectPass: req.session.projectPass,
'configs': configs
}, function(err, data) {
res.send(data)
})
} else
res.redirect('/')
})
app.get('/projects-mixly', function(req, res) {
ejs.renderFile(__dirname + '/ejs/projects.ejs', {
isMixly: 1,
userName: req.session.userName,
projectPass: req.session.projectPass,
count: 0,
prjid: req.query.prjid ? req.query.prjid : 'no',
'configs': configs
}, function(err, data) {
res.send(data)
})
})
app.post('/importProjects', function(req, res) {
var userName = req.session.userName
var projectName = req.body.projectName
if (userName && projectName) {
var projectType = req.body.projectType
var projectLayout = req.body.projectLayout
var dataStorage = req.body.dataStorage
var logicStorage = req.body.logicStorage
db.run("delete from `project` where userName=? and projectName=?", [userName, projectName], function(err) {
db.get("select COUNT(*) from `project` where userName=?", [userName], function(err, row) {
if (err)
console.log(err)
else
if (row["COUNT(*)"] >= configs['MAX_PROJECT_NUM_PER_USER'])
res.send('3')
else
db.run("insert into `project` (projectName,userName,projectLayout,projectType,dataStorage,logicStorage) values(?,?,?,?,?,?)", [projectName, userName, projectLayout, projectType, dataStorage, logicStorage], function(err) {
if (err)
console.log(err)
else
res.send('1')
})
})
})
}
})
app.get('/exportProjects', function(req, res) {
if (req.session.userName) {
var userName = req.session.userName
db.all("select * from `project` where userName=?", [userName], function(err, rows) {
res.send(JSON.stringify(rows))
})
}
})
app.get('/getData', function(req, res) {
if (req.session.userName) {
var userName = req.session.userName
var hash = 0,i, chr;
for (i = 0; i < userName.length; i++) {
chr = userName.charCodeAt(i);
hash = ((hash << 5) - hash) + chr;
hash |= 0;
}
reserveDBs[Math.abs(hash) % 8].all("select * from `reserve` where userName=?", [req.session.userName], function(err, rows) {
if (err) {
console.log(err)
} else {
if (rows) {
res.send({
"count": rows.length,
"rows": rows,
"max": configs['MAX_MESSAGE_PER_USER']
})
}
}
})
}
})
app.get('/getProjects', function(req, res) {
if (req.session.userName && req.query.page) {
var pageStart = parseInt(req.query.page) * 8
db.get("select COUNT(*) from `project` where userName=?", [req.session.userName], function(err, row) {
var count = row['COUNT(*)']
db.all("select projectName,projectLayout,timestamp,projectType,userName from `project` where userName=? order by timestamp desc limit ?,8", [req.session.userName, pageStart], function(err, rows) {
resrows = JSON.parse(JSON.stringify(rows))
for (r in resrows) {
resrows[r]['isTask'] = 0
}
if (tasks[req.session.userName]) {
for (r in resrows) {
var prjName = resrows[r]['projectName']
var userTasks = tasks[req.session.userName]
var isTask = 0
for (task in userTasks) {
if (userTasks[task]["projectName"] == prjName) {
isTask = 1
if (userTasks[task]["closure"].errorMessage != "") {
isTask = resrows[r]['errorMessage'] = userTasks[task]["closure"].errorMessage
}
break
}
}
resrows[r]['isTask'] = isTask
}
}
res.send(JSON.stringify({
rows: resrows,
count: count
}))
})
})
} else
res.send('-1')
})
app.get('/modifyShare', function(req, res) {
if (req.session.userName && req.query.shareid && req.query.method) {
if (req.query.method == 2) {
db.run("delete from `share_key` where share_key=?", [req.query.shareid], function(err) {
if (err)
console.log(err)
else {
db.run("delete from `share` where shareid=?", [req.query.shareid], function(err) {
if (err) {
console.log(err)
res.send('2')
} else
res.send('1')
})
}
})
} else if (req.query.method == 1 || req.query.method == 0) {
db.run("update `share` set status = ? where shareid=?", [req.query.method, req.query.shareid], function(err) {
if (err) {
console.log(err)
res.send('2')
} else
res.send('1')
})
} else
res.send('2')
} else
res.redirect('/')
})
app.get('/share', function(req, res) {
if (req.session.userName && req.query.projectName) {
var userName = req.session.userName
var projectName = req.query.projectName
var shareid = md5(userName + projectName).substring(0, 6)
db.run("delete from `share` where userName=? and projectName=?", [req.session.userName, req.query.projectName], function(err) {
if (err)
console.log(err)
else {
db.run("insert into `share` (shareid, userName, projectName, projectLayout, dataStorage, logicStorage) values(?,?,?,(select projectLayout from `project` where userName = ? and projectName = ?),(select dataStorage from `project` where userName = ? and projectName = ?),(select logicStorage from `project` where userName = ? and projectName = ?))", [shareid, userName, projectName, userName, projectName, userName, projectName, userName, projectName], function(err) {
if (err)
console.log(err)
else {
db.run("delete from `share_key` where userName=? and projectName=?", [req.session.userName, req.query.projectName], function(err) {
if (err)
console.log(err)
else {
db.run("insert into `share_key` (userName,projectPass,projectName,share_key) values (?,?,?,?)", [req.session.userName, req.session.projectPass, req.query.projectName, shareid], function(err) {
if (err)
console.log(err)
else
res.send(shareid)
})
}
})
}
})
}
})
} else
res.redirect('/')
})
app.get('/getShare', function(req, res) {
if (req.session.userName && req.query.shareid) {
db.get("select * from `share` where shareid=?", [req.query.shareid], function(err, row) {
if (err)
console.log(err)
else {
if (row && row["status"] == 1) {
var userName = req.session.userName
var projectName = row['shareid'];
var projectCount = parseInt(row['shareCount']) + 1;
projectName = projectName + projectCount
db.run("update `share` set shareCount = ? where shareid=?", [projectCount, req.query.shareid], function(err) {
if (err) {
console.log(err)
res.send(err)
} else {
db.run("insert into `project`(projectName, userName, projectLayout, dataStorage, logicStorage) values(?,?,(select projectLayout from `share` where shareid = ?),(select dataStorage from `share` where shareid = ?),(select logicStorage from `share` where shareid = ?))", [projectName, userName, req.query.shareid, req.query.shareid, req.query.shareid], function(err) {
if (err) {
console.log(err)
res.send(err)
} else
res.send('1')
})
}
})
} else
res.send('2')
}
})
} else
res.redirect('/')
})
app.post('/getProject', function(req, res) {
var projectName = req.body.projectName
if (req.session.userName && projectName) {
db.get("select * from `project` where userName=? and projectName=?", [req.session.userName, projectName], function(err, row) {
if (row) {
var result = {}
result['userName'] = req.session.userName
result['projectPass'] = req.session.projectPass
result['projectLayout'] = row['projectLayout']
result['dataStorage'] = row['dataStorage']
result['logicStorage'] = row['logicStorage']
result['history'] = []
res.send(JSON.stringify(result))
} else
res.send('0')
})
} else
res.redirect('/')
})
app.post('/getHostProject', function(req, res) {
var userName = req.body.userName
var projectName = req.body.projectName
var projectPass = req.body.projectPass
db.get("select * from `project` where userName=? and projectName=?", [userName, projectName], function(err, row) {
if (row) {
var result = {}
result['userName'] = userName
result['projectPass'] = projectPass
result['projectLayout'] = row['projectLayout']
result['dataStorage'] = row['dataStorage']
result['logicStorage'] = row['logicStorage']
res.send(JSON.stringify(result))
} else
res.send('0')
})
})
app.post('/saveProject', function(req, res) {
var projectLayout = req.body.layout
var projectName = req.body.projectName
var projectType = req.body.projectType
var dataStorage = req.body.dataStorage
var logicStorage = req.body.logicStorage
if (req.session.userName && projectName && projectType && dataStorage && logicStorage && projectLayout) {
db.run("update `project` set projectLayout=?, dataStorage=?, logicStorage=?, projectType=? where userName=? and projectName=?", [projectLayout, dataStorage, logicStorage, projectType, req.session.userName, projectName], function(err) {
if (err) {
res.send(err)
} else {
res.send('1')
}
})
} else
res.send('会话已过期')
})
app.post('/saveLay', function(req, res) {
var projectLayout = req.body.layout
var projectName = req.body.projectName
var userName = req.body.userName
if (projectLayout && projectName && userName) {
db.run("update `project` set projectLayout=? where userName=? and projectName=?", [projectLayout, userName, projectName], function(err) {
if (err)
res.send('-1')
else
res.send('1')
})
}
})
app.get('/getSession', function(req, res) {
result = {}
if (req.session.userName) {
result['userName'] = req.session.userName
result['flag'] = true
} else
result['flag'] = false
res.send(JSON.stringify(result))
})
app.get('/queryShareKey', function(req, res) {
if (req.session.userName && req.query.projectName && req.query.projectPass) {
var userName = req.session.userName
var projectName = req.query.projectName
var projectPass = req.query.projectPass
db.get("select share_key from `share_key` where userName=? and projectPass=? and projectName=?", [userName, projectPass, projectName], function(err, row) {
if (row) {
res.send(JSON.stringify(row))
} else {
res.send('-1')
}
})
} else
res.redirect('/')
})
app.get('/login', function(req, res) {
var userName = req.query.userName
var password = req.query.password
var directLogin = req.query.directLogin
if (userName && password)
if(directLogin)
{
db.get("select * from `user` where username=?", [userName], function(err, row) {
if (row) {
if (row['password'] == md5(password + row['salt'])) {
if (row['verified'] == 1) {
req.session.userName = row['username']
req.session.projectPass = row['password']
if (req.session.salt)
req.session.salt = undefined
res.redirect('/projects')
} else {
req.session.userName = row['username']
req.session.salt = row['salt']
res.redirect('/verify')
}
} else
res.send('Invalid Username or Password')
} else
res.send('Invalid Username or Password')
})
}
else
{
db.get("select * from `user` where username=?", [userName], function(err, row) {
if (row) {
if (row['password'] == md5(password + row['salt'])) {
if (row['verified'] == 1) {
req.session.userName = row['username']
req.session.projectPass = row['password']
if (req.session.salt)
req.session.salt = undefined
res.send('1')
} else {
req.session.userName = row['username']
req.session.salt = row['salt']
res.send('3')
}
} else
res.send('2')
} else
res.send('2')
})
}
else
res.send('2')
})
app.get('/createProject', function(req, res) {
if (req.session.userName && req.query.projectName && req.query.projectType) {
var userName = req.session.userName
var projectName = req.query.projectName
var projectType = req.query.projectType
var projectInfo = '{"layout_info":[]}';
db.get("select COUNT(*) from `project` where userName=? and projectName=?", [userName, projectName], function(err, row) {
if (err)
console.log(err)
else
if (row["COUNT(*)"] > 0)
res.send('2')
else {
db.get("select COUNT(*) from `project` where userName=?", [userName], function(err, row) {
if (err)
console.log(err)
else
if (row["COUNT(*)"] >= configs['MAX_PROJECT_NUM_PER_USER'])
res.send('3')
else
db.run("insert into `project` (projectName,userName,projectLayout,projectType) values(?,?,?,?)", [projectName, userName, projectInfo, projectType], function(err) {
if (err)
console.log(err)
else
res.send('1')
})
})
}
})
} else
res.redirect('/')
})
app.get('/renameProject', function(req, res) {
if (req.session.userName && req.query.oldProjectName && req.query.newProjectName) {
var userName = req.session.userName
var oldProjectName = req.query.oldProjectName
var newProjectName = req.query.newProjectName
db.get("select * from `project` where userName=? and projectName=?", [userName, newProjectName], function(err, row) {
if (err)
console.log(err)
else
if (row)
res.send('2')
else {
db.run("update `project` set projectName=? where userName=? and projectName=?", [newProjectName, userName, oldProjectName], function(err) {
if (err)
console.log(err)
else {
res.send('1')
}
})
}
})
} else
res.redirect('/')
})
app.get('/copyProject', function(req, res) {
if (req.session.userName && req.query.oldProjectName && req.query.newProjectName) {
var userName = req.session.userName
var oldProjectName = req.query.oldProjectName
var newProjectName = req.query.newProjectName
db.get("select * from `project` where userName=? and projectName=?", [userName, newProjectName], function(err, row) {
if (err)
console.log(err)
else
if (row)
res.send('2')
else {
db.get("select COUNT(*) from `project` where userName=?", [userName], function(err, row) {
if (err)
console.log(err)
else
if (row["COUNT(*)"] >= configs['MAX_PROJECT_NUM_PER_USER'])
res.send('3')
else
db.run("insert into `project` (userName, projectLayout, dataStorage, logicStorage, projectName) VALUES (?,(select a.projectLayout from (select projectLayout from `project` where userName=? and projectName=?)a),(select a.dataStorage from (select dataStorage from `project` where userName=? and projectName=?)a),(select a.logicStorage from (select logicStorage from `project` where userName=? and projectName=?)a),?)", [userName, userName, oldProjectName, userName, oldProjectName, userName, oldProjectName, newProjectName], function(err) {
if (err)
console.log(err)
else
res.send('1')
})
})
}
})
} else
res.redirect('/')
})
app.post('/updateShareContent', function(req, res) {
if (req.session.userName && req.body.shareid && req.body.projectName && req.body.projectLayout && req.body.dataStorage && req.body.logicStorage) {
db.run("update `share` set projectLayout=?, dataStorage=?, logicStorage=?, projectName=? where shareid=? and userName=?", [req.body.projectLayout, req.body.dataStorage, req.body.logicStorage, req.body.projectName, req.body.shareid, req.session.userName], function(err) {
if (err)
console.log(err)
else
res.send('1')
})
} else
res.redirect('/')
})
app.get('/addShareKey', function(req, res) {
var rString = md5(req.session.userName + req.query.projectName).substring(0, 6)
if (req.session.userName && req.query.projectName && req.query.projectPass) {
db.run("delete from `share` where userName=? and projectName = ?", [req.session.userName, req.query.projectName], function(err) {
if (err)
console.log(err)
else {
db.run("insert into `share` (shareid, userName, projectName, projectLayout, dataStorage, logicStorage) values(?,?,?,(select projectLayout from `project` where userName = ? and projectName = ?),(select dataStorage from `project` where userName = ? and projectName = ?),(select logicStorage from `project` where userName = ? and projectName = ?))", [rString, req.session.userName, req.query.projectName, req.session.userName, req.query.projectName, req.session.userName, req.query.projectName, req.session.userName, req.query.projectName], function(err) {
if (err)
console.log(err)
else {
db.run("delete from `share_key` where userName=? and projectPass=? and projectName=?", [req.session.userName, req.query.projectPass, req.query.projectName], function(err) {
if (err)
console.log(err)
else {
db.run("insert into `share_key` (userName,projectPass,projectName,share_key) values (?,?,?,?)", [req.session.userName, req.query.projectPass, req.query.projectName, rString], function(err) {
if (err) {
console.log(err)
res.send(err)
} else {
res.send(rString)
}
})
}
})
}
})
}
})
} else
res.redirect('/')
})
app.get('/removeShareKey', function(req, res) {
if (req.session.userName && req.query.projectName && req.query.projectPass) {
db.run("delete from `share` where userName=? and projectName=?", [req.session.userName, req.query.projectName], function(err) {
if (err)
console.log(err)
else {
db.run("delete from `share_key` where userName=? and projectPass=? and projectName=?", [req.session.userName, req.query.projectPass, req.query.projectName], function(err) {
if (err) {
console.log(err)
res.send(err)
} else {
res.send('1')
}
})
}
})
} else
res.redirect('/')
})
app.get('/getWeather', function(req, res) {
if (req.query.dsc_code && !configs["OFFLINE_MODE"]) {
if(globalWeather[req.query.dsc_code] && globalWeather[req.query.dsc_code].time && (new Date().getTime() - globalWeather[req.query.dsc_code].time) < 600000) {
res.send(globalWeather[req.query.dsc_code].data)
} else {
http.get('http://api.map.baidu.com/weather/v1/?district_id=' + req.query.dsc_code + '&data_type=now&ak=' + configs["BAIDU_MAP_SERVER_AK"], function(req2, res2) {
var html = ''
req2.on('data', function(data) {
html += data;
});
req2.on('end', function() {
globalWeather[req.query.dsc_code] = {
time: new Date().getTime(),
data: html
}
res.send(html)
});
})
}
} else
res.send('-1')
})
app.post('/deleteProject', function(req, res) {
if (req.session.userName && req.body.projectName) {
db.run("delete from `project` where userName=? and projectName=?", [req.session.userName, req.body.projectName], function(err) {
if (err)
res.send('2')
else
res.send('1')
})
} else
res.redirect('/')
})
app.get('/resetQuestion', function(req, res) {
if (req.query.target) {
db.get("select * from `user` where username=?", [req.query.target], function(err, row) {
if (err || !row)
res.send({
'code': 999,
'question': ''
})
else
res.send({
'code': 1,
'question': row['question']
})
})
}
})
app.get('/logout', function(req, res) {
req.session.destroy(function(err) {
res.redirect('/');
})
})
app.get('/keyLogin', function(req, res) {
if (req.query.userName) {
req.session.userName = '@' + req.query.userName
req.session.projectPass = 'MixIO_public'
db.get("select COUNT(*) from `project` where username=?", [req.session.userName], function(err, row) {
if (err) {
console.log(err)
res.send('-1')
} else {
if (row["COUNT(*)"] > 0) {
res.send('1')
} else {
var layout = '{"layout_info":[]}';
db.run("insert into `project` (projectName,userName,projectLayout,projectType) values('default',?,?,'1')", [req.session.userName, layout], function(err) {
if (err) {
console.log(err)
res.send('-1')
} else
res.send('1')
})
}
}
})
} else
res.send('-1')
})
app.get('/time.php', function(req, res) {
var date = new Date()
var day = date.getDay() - 1
if (day < 0)
day = 6
res.send([date.getFullYear(), date.getMonth() + 1, date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds(), day].join(','))
})
app.get('/mixio-php/sharekey.php', function(req, res) {
if (req.query.sk) {
db.get("select userName,userName as '0', projectName, projectName as '1' ,projectPass, projectPass as '2' from `share_key` where share_key = ?", [req.query.sk], function(err, row) {
if (err)
console.log(err)
else {
if (row)
res.send(row)
else
res.send('-1')
}
})
} else
res.send('-1')
})
app.get('/devAPI', function(req, res) {
res.sendFile(__dirname + "/ejs/" + "dev.html");
})
app.get('/startHost', function(req, res) {
var userName = req.session.userName
var projectName = req.query.projectName
var projectPass = req.session.projectPass
if (userName && projectName && projectPass)
startHost(userName, projectName, projectPass, function(status) {
res.send(status)
})
else
res.send('-1')
})
app.get('/queryHook', function(req, res) {
if (req.session.userName) {
if (reserveJSON[req.session.userName])
res.send('1')
else
res.send('2')
} else {
res.send('0')
}
})
var filterPath = "storage/reserve/filter.json"
if(!fs.existsSync(filterPath))
filterPath = path.join(__dirname, filterPath)
app.get('/startHook', function(req, res) {
if (req.session.userName) {
reserveJSON[req.session.userName] = true
fs.writeFileSync(filterPath, JSON.stringify(reserveJSON, false, 4))
res.send('1')
} else {
res.send('0')
}
})
app.get('/stopHook', function(req, res) {
if (req.session.userName) {
reserveJSON[req.session.userName] = false
fs.writeFileSync(filterPath, JSON.stringify(reserveJSON, false, 4))
res.send('1')
} else {
res.send('0')
}
})
app.get('/clearHook', function(req, res) {
if (req.session.userName) {
var condition = req.query.condition
var userName = req.session.userName
var hash = 0,i, chr;
for (i = 0; i < userName.length; i++) {
chr = userName.charCodeAt(i);
hash = ((hash << 5) - hash) + chr;
hash |= 0;
}
reserveDBs[Math.abs(hash) % 8].run("delete from `reserve` where userName = ? and " + condition, [userName, ], function(err) {
if (err) {
console.log(err.message)
res.send('-1')
} else
res.send('1')
})
} else
res.send('0')
})
app.get('/endHost', function(req, res) {
var userName = req.session.userName
var projectName = req.query.projectName
if (userName && projectName) {
endHost(userName, projectName, function() {
res.send('1')
})
} else
res.send('-1')
})
app.use('/js', express.static(path.join(__dirname, 'js')));
app.use('/css', express.static(path.join(__dirname, 'css')));
app.use('/img', express.static(path.join(__dirname, 'img')));
app.use('/fonts', express.static(path.join(__dirname, 'fonts')));
app.use('/blockly', express.static(path.join(__dirname, 'blockly')));
app.use('/icons', express.static(path.join(__dirname, 'icons')));
app.use('/documentation', express.static(path.join(__dirname, 'documentation')));
var mixlyPath = "../mixly"
if(fs.existsSync(mixlyPath)){
app.use('/mixly', express.static(mixlyPath));
}
var reserveJSON = JSON.parse(fs.readFileSync(filterPath), "utf8")
var oldListen = app.listen
app.listen = function(port, callback) {
if(port == 0)
callback()
else
oldListen.call(app, port, callback)
}
return new Promise(resolve => {
plainServer.listen(configs["MIXIO_MQTT_PORT"], function() {
console.log('[INFO] Plain MQTT server listening on port', configs["MIXIO_MQTT_PORT"])
httpServer.listen(configs["MIXIO_WS_PORT"], function() {
console.log('[INFO] WebSocket MQTT server listening on port', configs["MIXIO_WS_PORT"])
httpsServer.listen(configs["MIXIO_WSS_PORT"], function() {
console.log('[INFO] WebSocketS MQTT server listening on port', configs["MIXIO_WSS_PORT"])
httpServer2 = http.createServer(app)
httpServer2.listen(configs['MIXIO_HTTP_PORT'], function() {
if(configs['MIXIO_HTTP_PORT'] != 0)
console.log("[INFO] MixIO server listening on port", configs['MIXIO_HTTP_PORT'])
httpsServer2 = https.createServer(credentials, app)
httpsServer2.listen(configs['MIXIO_HTTPS_PORT'], function() {
if(configs['MIXIO_HTTPS_PORT'] != 0)
console.log("[INFO] MixIO server (HTTPS) listening on port", configs['MIXIO_HTTPS_PORT'])
var stopFunction = function() {
return new Promise(resolve => {
//MQTT
plainServer.close(function() {
console.log("[INFO] Plain MQTT server closed")
//MQTT Websocket
httpServer.close(function() {
console.log("[INFO] WebSocket MQTT server closed")
//MixIO HTTP
httpServer2.close(function() {
console.log("[INFO] MixIO server closed")
//MQTT WebsocketS
httpsServer.close(function() {
console.log("[INFO] WebSocketS MQTT server closed")
//MixIO HTTPS
httpsServer2.close(function() {
console.log("[INFO] MixIO server (HTTPS) closed")
resolve("1")
})
})
})
})
})
})
}
if(STORAGE_ENGINE == 'sqlite'){
var dbPath = "storage/mixio.db"
db = new sqlite3.Database(
dbPath,
sqlite3.OPEN_READWRITE,
function(err) {
if (err) {
console.log(err.message)
}
db.run('delete from devices')
console.log('[INFO] Storage Engine: SQLite')
console.log('[INFO] Database Connected!')
resolve({
stop: stopFunction
})
}
)
reserveDBs = []
for (var i = 1; i <= 8; i = i + 1) {
var dbPath = "storage/reserve/" + i + ".db"
if(!fs.existsSync(dbPath)) {
dbPath = path.join(__dirname,'./reserve/' + i + ".db")
}
reserveDBs.push(
new sqlite3.Database(
dbPath,
sqlite3.OPEN_READWRITE,
function(err) {
if (err)
console.log(err.message)
}
)
)
}
}
else if(STORAGE_ENGINE == 'mysql'){
db = mysql.createConnection({
host: MYSQL_HOST,
port: MYSQL_PORT,
user: MYSQL_USER,
password: MYSQL_PASS
})
db.get = function(sql, params, callback) {
db.query(sql, params, function(err, rows) {
if (err) {
callback(err, null)
} else {
callback(null, rows[0])
}
})
}
db.run = function(sql, params, callback) {
db.query(sql, params, function(err, result) {
if(err)
{
if(callback)
{
callback(err)
}
}
else if(callback)
callback()
})
}
db.all = function(sql, params, callback) {
db.query(sql, params, function(err, rows) {
if (err) {
callback(err, null)
} else {
callback(null, rows)
}
})
}
// create database if not exists
db.query('create database if not exists ' + MYSQL_DB, function(err) {
if (err) {
console.log(err.message)
}
db.query('use ' + MYSQL_DB, function(err) {
if (err) {
console.log(err.message)
}
init_mysql(function(status,reason){
if(status == "error")
console.log(reason)
else if(status == "success")
{
console.log("[INFO] Database Initialized!")
db.query('delete from devices')
console.log('[INFO] Storage Engine: MySQL (' + MYSQL_HOST + ')')
console.log('[INFO] Database Connected!')
resolve({
stop: stopFunction
})
}
})
})
})
reserveDBs = [db, db, db, db, db, db, db, db]
}
});
})
})
})
})
})
}
function init_mysql(cb){
db.query(`CREATE TABLE IF NOT EXISTS devices (
userName VARCHAR(255),
clientid VARCHAR(255),
timestamp timestamp DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY(clientid)
)`, function(err, result) {
if (err) {
cb("error", err)
}
else {
db.query(`CREATE TABLE IF NOT EXISTS project (
projectName VARCHAR(255),
userName VARCHAR(255),
projectLayout MEDIUMTEXT,
dataStorage MEDIUMTEXT,
logicStorage MEDIUMTEXT,
timestamp timestamp DEFAULT CURRENT_TIMESTAMP,
projectType INTEGER
)`, function(err, result) {
if (err) {
cb("error", err)
}
else {
db.query(`CREATE TABLE IF NOT EXISTS share (
shareid VARCHAR(255),
userName VARCHAR(255),
projectName VARCHAR(255),
projectLayout MEDIUMTEXT,
dataStorage MEDIUMTEXT,
logicStorage MEDIUMTEXT,
timeStamp timestamp DEFAULT CURRENT_TIMESTAMP,
status INTEGER DEFAULT 1,
shareCount INTEGER DEFAULT 0
)`, function(err, result) {
if (err) {
cb("error", err)
}
else {
db.query(`CREATE TABLE IF NOT EXISTS share_key (
userName VARCHAR(255),
projectPass VARCHAR(255),
projectName VARCHAR(255),
share_key VARCHAR(255)
)`, function(err, result) {
if (err) {
cb("error", err)
}
else {
db.query(`CREATE TABLE IF NOT EXISTS user (
id INTEGER AUTO_INCREMENT,
username VARCHAR(255),
password VARCHAR(255),
salt VARCHAR(255),
is_superuser INTEGER DEFAULT 0,
verified INTEGER DEFAULT 1,
question VARCHAR(255),
answer VARCHAR(255),
PRIMARY KEY(id)
)`, function(err, result) {
if(err){
cb("error", err)
}
else{
db.query(`CREATE TABLE IF NOT EXISTS reserve (
id INTEGER AUTO_INCREMENT,
userName VARCHAR(255),
topic VARCHAR(255),
message VARCHAR(1023),
time timestamp DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY(id)
)`,function(err, result) {
if(err){
cb("error", err)
}
else{
cb("success", null)
}
})
}
})
}
})
}
})
}
})
}
})
}
async function startOnce() {
mixio = await mixioServer()
}
const args = process.argv.slice(2)
var startMixIO = function(){
var parent_exit = function(child){
var logFile = fs.openSync(logFileName, 'r')
while(true){
// check log file for database connection
var data = fs.readFileSync(logFile, 'utf8')
if(data[data.length-1] == "\n")
data = data.slice(0, -1)
if(data!="")
console.log(data)
if(data.toString().indexOf("Database Connected!") != -1)
{
console.log("MixIO server is running now.")
child.unref()
for (var t = Date.now(); Date.now() - t <= 2000;);
process.exit()
}
else if(data.toString().indexOf("Error") != -1)
{
console.error("An error occured while initializing MixIO server. Log file: " + process.cwd() + logFileName)
child.unref()
for (var t = Date.now(); Date.now() - t <= 2000;);
process.exit()
}
}
}
// child process to run 'mixio' in background
var logFile = fs.openSync(logFileName, 'a')
if(process.argv[0].indexOf("node") != -1)
{
var child = spawn(process.argv[0], [process.argv[1], "debug"], { detached: true , stdio:['ignore', logFile, logFile]})
parent_exit(child)
}
else
{
var child = spawn(process.argv[0], [process.argv[1], "debug"], { detached: true , stdio:['ignore', logFile, logFile]})
parent_exit(child)
}
}
var stopMixIO = function(){
// kill 'mixio' process if it is running
if(process.argv[0].indexOf("node") != -1)
{
if(process.platform == "win32")
{
console.log("Shutting down MixIO server...")
exec('taskkill /F /IM node.exe', function(err, stdout, stderr) {
if (err) {
console.log(err)
}
})
}
else
{
console.log("Shutting down MixIO server...")
exec('pkill node', function(err, stdout, stderr) {
if (err) {
console.log(err)
}
})
}
}
else
{
if(process.platform == "win32")
{
console.log("Shutting down MixIO server...")
exec('taskkill /F /IM mixio.exe', function(err, stdout, stderr) {
if (err) {
console.log(err)
}
})
}
else
{
console.log("Shutting down MixIO server...")
exec('pkill mixio', function(err, stdout, stderr) {
if (err) {
console.log(err)
}
})
}
}
}
init(function(res){
if(res)
{
configPath = "config/config.json"
configs = fs.readFileSync(configPath);
configs = JSON.parse(configs.toString());
if(! configs["FOOTER"])
configs["FOOTER"] = ""
STORAGE_ENGINE = configs["STORAGE_ENGINE"]
MYSQL_HOST = configs["MYSQL_HOST"]
MYSQL_USER = configs["MYSQL_USER"]
MYSQL_PASS = configs["MYSQL_PASS"]
MYSQL_DB = configs["MYSQL_DB"]
MYSQL_PORT = configs["MYSQL_PORT"]
MAX_MESSAGE_PER_USER = configs["MAX_MESSAGE_PER_USER"]
MAX_MESSAGE_PER_SECOND = configs["MAX_MESSAGE_PER_SECOND"]
if (args.length > 1 || (args.length == 0 && process.platform != "win32")) {
console.log("Invalid parameter(s). Use \"mixio help\" for help.")
} else {
var show = function(){
if(args.length == 0){
// wait for user input, 1 for start, 2 for stop, 3 for autoStart, 4 for remove autoStart
console.log("1. Start MixIO server")
console.log("2. Stop MixIO server")
console.log("3. Set MixIO server to auto start")
console.log("4. Remove MixIO server from auto start")
console.log("5. Exit")
var rl = readline.createInterface({
input: process.stdin,
output: process.stdout
})
rl.question("Please select an option: ", function(answer) {
rl.close()
if (answer == "1") {
startMixIO()
} else if (answer == "2") {
stopMixIO()
} else if (answer == "3") {
var child = spawn("schtasks", ["/create", "/sc", "onlogon", "/tn", "MixIO", "/tr", process.execPath + " start", "/rl", "highest", "/f"])
child.stdout.on('data', function(data) {
// encode to ANSI
console.log(iconv.decode(data, 'cp936').toString())
})
child.stderr.on('data', function(data) {
// encode to ANSI
console.log(iconv.decode(data, 'cp936').toString())
})
child.on("close", function() {
show();
})
} else if (answer == "4") {
var child = spawn("schtasks", ["/delete", "/tn", "MixIO", "/f"])
child.stdout.on('data', function(data) {
// encode to ANSI
console.log(iconv.decode(data, 'cp936').toString())
})
child.stderr.on('data', function(data) {
// encode to ANSI
console.log(iconv.decode(data, 'cp936').toString())
})
child.on("close", function() {
show();
})
} else if (answer == "5") {
process.exit()
} else {
console.log("Invalid option.")
}
})
}
else if (args[0] == "debug")
{
if(res){
daemon_start()
startOnce()
}
}
else if (args[0] == "start")
{
startMixIO()
}
else if (args[0] == "stop")
{
stopMixIO()
}
else if (args[0] == "version")
{
console.log(VERSION)
}
else if (args[0] == "install" && process.platform == "linux")
{
var install_shell = `
service="
[UNIT]
Description=MixIO.Service
After=network.target
StartLimitIntervalSec=0
[Service]
Type=forking
Restart=always
RestartSec=1
WorkingDirectory="`+ process.argv[0].slice(0,process.argv[0].lastIndexOf("/"))+`"
ExecStart=`+ process.argv[0].slice(0,process.argv[0].lastIndexOf("/"))+`/mixio start
ExecStop=`+ process.argv[0].slice(0,process.argv[0].lastIndexOf("/"))+`/mixio stop
[Install]
WantedBy=multi-user.target
"
echo "$`+`{service}" > /etc/systemd/system/mixio.service
`
//output shell script to install.sh
fs.writeFileSync("install.sh", install_shell)
//run install.sh
exec('sh install.sh', function(err, stdout, stderr) {
if (err) {
console.log(err)
}
else
{
console.log(stdout)
}
}
)
}
else if (args[0] == "help")
{
console.log("MixIO server help:")
console.log("mixio start: start MixIO server in background.")
console.log("mixio stop: stop MixIO server.")
console.log("mixio debug: start MixIO server in foreground.")
console.log("mixio version: show MixIO server version.")
if(process.platform == "linux")
console.log("mixio install: install MixIO service.")
}
else
{
console.log("Invalid parameter(s). Use \"mixio help\" for help.")
}
}
show();
}
}
})
//MixIO
curlong = 0
curlati = 0
function MixIOLogicError(message) {
this.message = message
this.name = "MixIOLogicError"
}
MixIOLogicError.prototype = new Error()
var MixIOclosure = function(userName, projectName, projectPass, dataStorage, dom) {
var that = this
this.errorMessage = ""
this.dataSave = JSON.parse(dataStorage)
if (!this.dataSave || !this.dataSave["received"]) {
this.dataSave = {
"received": {}
}
}
this.lastPublishTime = [new Date(0), new Date(0), new Date(0), new Date(0), new Date(0), new Date(0), new Date(0), new Date(0), new Date(0), new Date(0), new Date(0), new Date(0), new Date(0), new Date(0), new Date(0), new Date(0), new Date(0), new Date(0), new Date(0), new Date(0)],
this.minPublishInterval = 500,
this.client = mqtt.connect('ws://localhost:' + configs["MIXIO_WS_PORT"], {
'clientId': "MixIO_" + Math.random().toString(16).substr(2, 8),
'username': userName,
'password': projectPass
}).on('connect', function() {
this.subscribe(userName + "/" + projectName + "/" + "#")
}).on('message', function(topic, message) {
var saveTopic = topic.split('/').pop()
var saveMessage = stringendecoder.encodeHtml(String(message))
var addJSON = {
"时间": timeStamp2String(),
"": saveMessage
}
if (saveTopic in that.dataSave["received"]) {
that.dataSave["received"][saveTopic].unshift(addJSON)
} else {
that.dataSave["received"][saveTopic] = [addJSON]
}
}),
this.publish = function(topic, message) {
var newPublishTime = new Date()
if (newPublishTime - this.lastPublishTime[0] >= this.minPublishInterval) {
this.client.publish(userName + '/' + projectName + '/' + topic.toString(), message.toString())
this.lastPublishTime.shift()
this.lastPublishTime.push(new Date())
} else {
//MixIO.log(JSLang[lang].speedLimit)
that.stop_project()
}
},
this.activedom = (new JSDOM("<div id='grid'></div>")).window,
this.$ = function(activedom) {
return jq(activedom)
}(this.activedom),
this.isRunning = true,
this.listeners_to_be_removed = [],
this.timers_to_be_removed = [],
this.cycles_to_be_removed = [],
this.stop_project = function() {
that.isRunning = false
this.client.end()
this.safe_pause()
db.run("update `project` set dataStorage=? where userName=? and projectName=?", [JSON.stringify(that.dataSave), userName, projectName], function(err) {})
},
this.safe_pause = function() {
this.isRunning = false
for (listener in this.listeners_to_be_removed) {
for (eventIndex in this.client._events.message) {
if (this.client._events.message[eventIndex] == this.listeners_to_be_removed[listener]) {
this.client._events.message.splice(eventIndex, 1)
break;
}
}
}
for (timer in this.timers_to_be_removed) {
clearTimeout(this.timers_to_be_removed[timer])
}
for (cycle in this.cycles_to_be_removed) {
clearInterval(this.cycles_to_be_removed[cycle])
}
this.listeners_to_be_removed = []
this.timers_to_be_removed = []
this.cycles_to_be_removed = []
for (tagIndex in this.eventTags)
this.$('*[user-title]').unbind(this.eventTags[tagIndex])
},
/*合法的MixIO组件种类*/
this.typeTags = {
BUTTON: 1,
SLIDER: 2,
KEYBOARD: 3,
JOYSTICK: 4,
RGB_PICKER: 5,
BULB: 6,
TEXT_SCREEN: 7,
LINE_CHART: 8,
BAR_CHART: 9,
DATA_TABLE: 10,
DASHBOARD: 11,
DATA_MAP: 12,
WEATHER: 13
},
this.oldTags = ["input_button", "input_slider", "input_keyboard", "input_controller", "input_rgb", "output_bulb", "output_text",
"output_chart", "output_bar", "table", "output_dashboard", "output_map", "input_weather"
],
this.zhcnTags = ["按键/开关", "滑杆", "文本输入", "摇杆手柄", "RGB色盘", "指示灯", "文本显示屏", "折线图表", "柱状图表", "数据表格", "仪表盘", "数据地图", "实时气象仪"],
this.log = function(){},
/*合法的MixIO事件种类*/
this.eventTags = {
MQTT_MESSAGE_RECEIVED: "11", //收到MQTT消息
BUTTON_PRESSED: "111", //按键被按下
BUTTON_LOOSED: "112", //按键/开关被松开
BUTTON_CHANGED: "113", //按键/开关收到消息
SLIDER_SLIDED: "211", //滑杆被拖动
SLIDER_CHANGED: "212", //滑杆收到消息
KEYBOARD_SENT: "311", //键盘发送消息
JOYSTICK_CHANGED: "411", //摇杆被拖动
RGB_PICKER_PICKED: "511", //RGB色盘被选色
RGB_PICKER_CHANGED: "512", //RGB色盘收到消息
BULB_CHANGED: "611", //指示灯收到消息
TEXT_SCREEN_CHANGED: "711", //文本显示屏收到消息
LINE_CHART_CHANGED: "811", //折线图表收到消息
BAR_CHART_CHANGED: "911", //柱状图表收到消息
DATA_TABLE_CHANGED: "1011", //数据表格收到消息
DASHBOARD_CHANGED: "1111", //仪表盘收到消息
DATA_MAP_CHANGED: "1211", //数据地图收到消息
WEATHER_SYNCED: "1311", //气象仪更新数据
WEATHER_SENT: "1312" //气象仪发送数据
},
/*合法的MixIO行为种类*/
this.actionTags = {
SEND_MQTT_MESSAGE: "21", //发送MQTT消息
BUTTON_SWITCH: "121", //切换开关状态
SLIDER_SEND: "221", //改变滑杆数值
KEYBOARD_SEND: "321", //通过键盘发送消息
JOYSTICK_SEND: "421", //通过摇杆发送位置消息
RGB_PICKER_SEND: "521", //通过RGB色盘发送消息
BULB_CHANGE: "621", //向指示灯发送消息
TEXT_SCREEN_CHANGE: "721", //向文本显示屏发送消息
LINE_CHART_CHANGE: "821", //向折线图表发送消息
LINE_CHART_CLEAR: "822", //清空折线图表消息
BAR_CHART_CHANGE: "921", //向柱状图表发送消息
BAR_CHART_CLEAR: "922", //清空柱状图表消息
DATA_TABLE_CHANGE: "1021", //向数据表格发送消息
DATA_TABLE_CLEAR: "1022", //清空数据表格消息
DASHBOARD_CHANGE: "1121", //向仪表盘发送消息
DATA_MAP_CHANGE: "1221", //向数据地图发送消息
DATA_MAP_CLEAR: "1222", //清空数据地图数据
WEATHER_SYNC: "1321", //更新气象仪数据
WEATHER_SEND: "1322" //发送气象仪数据
},
this.setInterval = function(triggerFunction, intervalTime) {
this.cycles_to_be_removed.push(setInterval(
function() {
try {
triggerFunction()
} catch (e) {
console.log(e.message)
that.errorMessage = e.toString()
that.stop_project()
}
}, intervalTime))
},
this.setTimeout = function(triggerFunction, waitTime) {
this.timers_to_be_removed.push(setTimeout(
function() {
try {
triggerFunction()
} catch (e) {
that.errorMessage = e.toString()
that.stop_project()
}
}, waitTime))
},
this.onMessage = function(trigger) {
var toBeRemoved = function(topic, message) {
var splitTopic = topic.split('/').pop()
try {
trigger(splitTopic, message)
} catch (e) {
that.errorMessage = e.toString()
that.stop_project()
}
}
this.client.on("message", toBeRemoved)
this.listeners_to_be_removed.push(toBeRemoved)
},
this.isValidType = function(typeTag) {
for (target in this.typeTags) {
if (typeTag === this.typeTags[target])
return true;
}
return false;
},
/*获取组件实例*/
this.getInstance = function(name, type) {
if (!this.isValidType(type))
throw new MixIOLogicError(JSLang[lang].invalidUType)
var instance = this.$("[" + "user-title='" + name + "']")
if (instance.length != 1)
throw new MixIOLogicError(JSLang[lang].noUnitFound)
if (instance.attr("user-type") != this.oldTags[type - 1])
throw new MixIOLogicError(JSLang[lang].invalidUType)
instance.toString = function() {
return this.zhcnTags[type - 1] + ":" + name
}
if (type === this.typeTags.BUTTON) {
//获取开关状态
instance.isOn = function() {
return instance.attr('user-content') == '1'
}
} else if (type === this.typeTags.SLIDER) {
//获取滑杆数值
instance.getValue = function() {
return parseFloat(instance.attr('user-content').split(',')[3])
}
} else if (type === this.typeTags.JOYSTICK) {
//获取摇杆横坐标
instance.getX = function() {
return parseInt(instance.attr('user-content').split(',')[0])
}
//获取摇杆纵坐标
instance.getY = function() {
return parseInt(instance.attr('user-content').split(',')[1])
}
} else if (type === this.typeTags.KEYBOARD) {
instance.getText = function() {
return instance.attr('user-content')
}
} else if (type === this.typeTags.RGB_PICKER) {
//获取RGB色盘当前颜色
instance.getColor = function() {
var tmp = instance.attr('user-content').split(',')
for (i in tmp) {
tmp[i] = parseInt(tmp[i])
}
return tmp
}
} else if (type === this.typeTags.BULB) {
//获取指示灯当前状态
instance.getStatus = function() {
return instance.attr('user-content')
}
} else if (type === this.typeTags.TEXT_SCREEN) {
//获取文本显示屏的当前显示
instance.getText = function() {
return instance.attr('user-content')
}
} else if (type === this.typeTags.LINE_CHART) {
var allJSON = []
if (instance.attr('user-content').length > 2) {
var allMsg = JSON.parse(stringendecoder.decodeHtml(instance.attr('user-content').slice(2)))
var prevX = allMsg.prevX.data
var series = allMsg.series
for (i in prevX) {
let oneJSON = {}
let j = i
oneJSON.time = prevX[j]
for (sery in series)
oneJSON[series[sery].name] = series[sery]['data'][j]
allJSON.push(oneJSON)
}
}
//获取折线图表的全部历史消息
instance.getAllMessages = function(index) {
return allJSON
}
//获取折线图表的至多前num条消息
instance.getLatestMessages = function(num) {
return allJSON.slice(0 - num)
}
//获取折线图表的最新一条消息
instance.getLatestMessage = function(index) {
return allJSON.slice(-1)
}
} else if (type === this.typeTags.BAR_CHART) {
var allMsg = instance.attr('user-content').slice(2).split(',')
var sepMsgs = {
keys: [],
values: []
}
var count = allMsg.length / 2
for (msg in allMsg) {
if (msg < count)
sepMsgs.keys.push(allMsg[msg])
else
sepMsgs.values.push(allMsg[msg])
}
//获取柱状图表的当前数据
instance.getData = function() {
return sepMsgs
}
} else if (type === this.typeTags.DATA_TABLE) {
var allMsg = instance.attr('user-content').split(',')
var sepMsgs = {}
var colCount = parseInt(allMsg[0])
for (var i = 0; i < colCount; i = i + 1) {
sepMsgs[allMsg[i + 1]] = []
}
for (var i = 1 + colCount; i < allMsg.length; i = i + 1) {
sepMsgs[allMsg[(i - 1 - colCount) % colCount + 1]].push(allMsg[i])
}
//获取数据表格的全部数据
instance.getData = function() {
return sepMsgs
}
} else if (type === this.typeTags.DASHBOARD) {
//获取仪表盘的当前值
instance.getValue = function() {
return instance.attr('user-content').split(',')[2]
}
} else if (type === this.typeTags.WEATHER) {
var sepMsgs = {
district: instance.attr('user-content').split(',')[1],
weather_type: instance.attr('user-content').split(',')[2],
temperature: instance.attr('user-content').split(',')[3],
humidity: instance.attr('user-content').split(',')[4],
wind_dir: instance.attr('user-content').split(',')[5],
wind_class: instance.attr('user-content').split(',')[6]
}
//获取气象仪的信息
instance.getData = function(type) {
return sepMsgs[type]
}
}
return instance
},
this.getClientid = function() {
return this.client.options.clientId
},
this.getLong = function() {
return curlong
},
this.getLati = function() {
return curlati
},
this.makedom = function() {
var grid = that.$("#grid")
var client = that.client
var units_array = that.$(dom)
var $ = that.$
var isMixly = false
var MixIO = that
var add_block = function(width, height, contents, attrs) {
var itemdiv = $("<div/>")
itemdiv.attr("class", "item")
contentdiv = $("<div/>")
contentdiv.attr("class", "item-content")
for (content in contents)
contentdiv.append(contents[content])
for (attr in attrs)
itemdiv.attr(attrs[attr][0], attrs[attr][1])
itemdiv.append(contentdiv)
grid.append(itemdiv[0])
return itemdiv
}
var toolkits = {
'input_button': function(user_title, user_topic, user_content, user_style) {
var isAlive = true
var contents = []
var title = $("<h4 class='userTitle'>" + user_title + "</h4>")
contents.push(title)
var topicDiv = $("<div class='topicDiv'/>")
var topic = $("<span class='index-topic' style='margin:0;color:#858796;'>" + user_topic + "</span>")
topicDiv.append($("<i class='fa fa-podcast' style='color:#858796;margin-right:3px'></i>"))
topicDiv.append(topic)
var button = $("<label class='switch' style='margin-bottom:0'></label>")
var button2 = $("<a class='pushButton'/>")
var checkbox = $("<input type='checkbox'>")
if (user_content == 1)
checkbox.prop('checked', true)
else
checkbox.prop('checked', false)
var checkDiv = $("<div class='slider round'></div>")
button.append(checkbox)
button.append(checkDiv)
contents.push(button)
contents.push(button2)
client.on('message', function(topic1, message1) {
if (isAlive && that.isRunning)
if (title.parent().parent().attr('user-content') != 2 && topic1.split("/")[(isMixly ? 3 : 2)] == topic.text()) {
if (message1 == 0) {
checkbox.prop('checked', false)
title.parent().parent().attr('user-content', 0)
} else if (message1 == 1) {
checkbox.prop('checked', true)
title.parent().parent().attr('user-content', 1)
}
itemdiv.trigger(MixIO.eventTags.BUTTON_CHANGED, [Uint8ArrayToString(message1)])
}
})
attrs = [
['user-type', 'input_button'],
['user-title', user_title],
['user-topic', user_topic],
['user-content', user_content]
]
var itemdiv = add_block(1, 1, contents, attrs)
itemdiv.bind(MixIO.actionTags.BUTTON_SWITCH, function(event, status) {
checkbox.prop('checked', !!status)
MixIO.publish(topic.text(), (!!status) ? 1 : 0)
})
},
'input_slider': function(user_title, user_topic, user_content, user_style) {
var isAlive = true
var contents = []
var title = $("<h4 class='userTitle'>" + user_title + "</h4>")
contents.push(title)
var topicDiv = $("<div class='topicDiv'/>")
var topic = $("<span class='index-topic' style='margin:0;color:#858796;'>" + user_topic + "</span>")
topicDiv.append($("<i class='fa fa-podcast' style='color:#858796;margin-right:3px'></i>"))
topicDiv.append(topic)
var sliderDiv = $("<div style='width:100%;display:flex;flex-direction:row;justify-content:center'/>")
var slider = $("<input type='range' min='0' max='10' step='1' value='0'></input>")
sliderDiv.append(slider)
contents.push(sliderDiv)
attrs = [
['user-type', 'input_slider'],
['user-title', user_title],
['user-topic', user_topic],
['user-content', user_content]
]
var itemdiv = add_block(3, 1, contents, attrs)
client.on('message', function(topic1, message1) {
if (isAlive && that.isRunning)
if (topic1.split("/")[(isMixly ? 3 : 2)] == topic.text()) {
if (!isNaN(parseFloat(message1))) {
var val = parseFloat(message1)
if (val >= slider.attr('min') && val <= slider.attr('max')) {
slider.val(val)
title.parent().parent().attr('user-content', slider.attr('min') + "," + slider.attr('max') + "," + slider.attr('step') + "," + slider.val())
}
}
itemdiv.trigger(MixIO.eventTags.SLIDER_CHANGED, [parseFloat(message1)])
}
})
itemdiv.bind(MixIO.actionTags.SLIDER_SEND, function(event, val) {
if (val >= slider.attr('min') && val <= slider.attr('max')) {
slider.val(val)
}
MixIO.publish(topic.text(), val)
})
var vals = user_content.split(',')
slider.attr('min', vals[0])
slider.attr('max', vals[1])
slider.attr('step', vals[2])
slider.val(vals[3])
},
'input_keyboard': function(user_title, user_topic, user_content, user_style) {
var isAlive = true
var contents = []
var title = $("<h4 class='userTitle'>" + user_title + "</h4>")
contents.push(title)
var topicDiv = $("<div class='topicDiv'/>")
var topic = $("<span class='index-topic' style='margin:0;color:#858796;'>" + user_topic + "</span>")
topicDiv.append($("<i class='fa fa-podcast' style='color:#858796;margin-right:3px'></i>"))
topicDiv.append(topic)
attrs = [
['user-type', 'input_keyboard'],
['user-title', user_title],
['user-topic', user_topic],
['user-content', user_content]
]
var keyDiv = $("<div style='width:100%;display:flex;flex-direction:row;justify-content:center;align-items:center'/>")
var messDiv = $("<input class='form-control' style='width:70%;min-width:0px'/>")
messDiv.val(stringendecoder.decodeHtml(user_content))
keyDiv.append(messDiv)
contents.push(keyDiv)
var itemdiv = add_block(3, 1, contents, attrs)
itemdiv.bind(MixIO.actionTags.KEYBOARD_SEND, function(event, message) {
messDiv.val(message)
MixIO.publish(topic.text(), messDiv.val())
})
},
'input_controller': function(user_title, user_topic, user_content, user_style) {
var isAlive = true
var contents = []
var title = $("<h4 class='userTitle'>" + user_title + "</h4>")
contents.push(title)
var topicDiv = $("<div class='topicDiv'/>")
var topic = $("<span class='index-topic' style='margin:0;color:#858796;'>" + user_topic + "</span>")
topicDiv.append($("<i class='fa fa-podcast' style='color:#858796;margin-right:3px'></i>"))
topicDiv.append(topic)
var controllerDiv = $("<div style='width:70%;height:70%;'/>")
contents.push(controllerDiv)
attrs = [
['user-type', 'input_controller'],
['user-title', user_title],
['user-content', "0,0"],
['user-topic', user_topic]
]
var itemdiv = add_block(2, 2, contents, attrs)
itemdiv.bind(MixIO.actionTags.JOYSTICK_SEND, function(event, x, y) {
MixIO.publish(topic.text(), x + "," + y)
})
},
'input_rgb': function(user_title, user_topic, user_content, user_style) {
var isAlive = true
var contents = []
var title = $("<h4 class='userTitle'>" + user_title + "</h4>")
contents.push(title)
var topicDiv = $("<div style='margin-top:5px;margin-bottom:5px;font-size:0.75rem'/>")
var Rtopic = $("<span class='index-topic' style='margin:0;color:#858796;;margin-right:10px'>" + user_topic.split('/')[0] + "</span>")
topicDiv.append($("<i class='fa fa-podcast' style='color:#e74a3b;margin-right:3px'></i>"))
topicDiv.append(Rtopic)
var Gtopic = $("<span class='index-topic' style='margin:0;color:#858796;;margin-right:10px'>" + user_topic.split('/')[1] + "</span>")
topicDiv.append($("<i class='fa fa-podcast' style='color:#1cc88a;margin-right:3px'></i>"))
topicDiv.append(Gtopic)
var Btopic = $("<span class='index-topic' style='margin:0;color:#858796;'>" + user_topic.split('/')[2] + "</span>")
topicDiv.append($("<i class='fa fa-podcast' style='color:#4e73df;margin-right:3px'></i>"))
topicDiv.append(Btopic)
var RGBDiv = $("<div style='color:black;margin-right:10px;display:flex;flex-direction:column;align-items:center'/>")
var RDiv = $("<div style='display:flex;flex-direction:row;align-items:center;justify-content:center;margin-top:5px;margin-bottom:5px'/>")
var GDiv = $("<div style='display:flex;flex-direction:row;align-items:center;justify-content:center;margin-top:5px;margin-bottom:5px'/>")
var BDiv = $("<div style='display:flex;flex-direction:row;align-items:center;justify-content:center;margin-top:5px;margin-bottom:5px'/>")
var RInput = $("<input class='form-control' style='width:45px;padding:3px;min-width:0px' readonly>")
var GInput = $("<input class='form-control' style='width:45px;padding:3px;min-width:0px' readonly>")
var BInput = $("<input class='form-control' style='width:45px;padding:3px;min-width:0px' readonly>")
RInput.val(user_content.split(',')[0])
GInput.val(user_content.split(',')[1])
BInput.val(user_content.split(',')[2])
RDiv.append(RInput)
GDiv.append(GInput)
BDiv.append(BInput)
RGBDiv.append(RDiv)
RGBDiv.append(GDiv)
RGBDiv.append(BDiv)
contents.push(RGBDiv)
attrs = [
['user-type', 'input_rgb'],
['user-title', user_title],
['user-topic', user_topic],
['user-content', user_content]
]
var itemdiv = add_block(3, 3, contents, attrs)
itemdiv.bind(MixIO.actionTags.RGB_PICKER_SEND, function(event, r, g, b) {
MixIO.publish(Rtopic.text(), r)
MixIO.publish(Gtopic.text(), g)
MixIO.publish(Btopic.text(), b)
})
client.on('message', function(topic1, message1) {
if (isAlive && that.isRunning)
if (topic1.split("/")[(isMixly ? 3 : 2)] == Rtopic.text()) {
if (!isNaN(parseInt(message1))) {
var val = parseInt(message1)
if (val >= 0 && val <= 255) {
RInput.val(val)
title.parent().parent().attr('user-content', RInput.val() + "," + GInput.val() + "," + BInput.val())
itemdiv.trigger(MixIO.eventTags.RGB_PICKER_CHANGED, [val, -1, -1])
}
}
}
if (isAlive && that.isRunning)
if (topic1.split("/")[(isMixly ? 3 : 2)] == Gtopic.text()) {
if (!isNaN(parseInt(message1))) {
var val = parseInt(message1)
if (val >= 0 && val <= 255) {
GInput.val(val)
title.parent().parent().attr('user-content', RInput.val() + "," + GInput.val() + "," + BInput.val())
itemdiv.trigger(MixIO.eventTags.RGB_PICKER_CHANGED, [-1, val, -1])
}
}
}
if (isAlive && that.isRunning)
if (topic1.split("/")[(isMixly ? 3 : 2)] == Btopic.text()) {
if (!isNaN(parseInt(message1))) {
var val = parseInt(message1)
if (val >= 0 && val <= 255) {
BInput.val(val)
title.parent().parent().attr('user-content', RInput.val() + "," + GInput.val() + "," + BInput.val())
itemdiv.trigger(MixIO.eventTags.RGB_PICKER_CHANGED, [-1, -1, val])
}
}
}
})
},
'output_bulb': function(user_title, user_topic, user_content, user_style) {
var isAlive = true
var contents = []
var title = $("<h4 class='userTitle'>" + user_title + "</h4>")
contents.push(title)
var topicDiv = $("<div class='topicDiv'/>")
var topic = $("<span class='index-topic' style='margin:0;color:#858796;'>" + user_topic + "</span>")
topicDiv.append($("<i class='fa fa-podcast' style='color:#858796;margin-right:3px'></i>"))
topicDiv.append(topic)
attrs = [
['user-type', 'output_bulb'],
['user-title', user_title],
['user-topic', user_topic],
['user-content', user_content]
]
var itemdiv = add_block(1, 1, contents, attrs)
itemdiv.bind(MixIO.actionTags.BULB_CHANGE, function(event, status) {
MixIO.publish(topic.text(), status)
})
client.on('message', function(topic1, message1) {
if (isAlive && that.isRunning)
if (topic1.split("/")[(isMixly ? 3 : 2)] == topic.text()) {
if (message1 == 0) {
title.parent().parent().attr('user-content', 0)
} else if (message1 == 1) {
title.parent().parent().attr('user-content', 1)
} else if (message1 == 2) {
title.parent().parent().attr('user-content', 2)
} else if (message1 == 3) {
title.parent().parent().attr('user-content', 3)
}
itemdiv.trigger(MixIO.eventTags.BULB_CHANGED, [Uint8ArrayToString(message1)])
}
})
},
'output_text': function(user_title, user_topic, user_content, user_style) {
var isAlive = true
var contents = []
var title = $("<h4 class='userTitle'>" + user_title + "</h4>")
contents.push(title)
var topicDiv = $("<div class='topicDiv'/>")
var topic = $("<span class='index-topic' style='margin:0;color:#858796;'>" + user_topic + "</span>")
topicDiv.append($("<i class='fa fa-podcast' style='color:#858796;margin-right:3px'></i>"))
topicDiv.append(topic)
var textDiv = $("<div/>")
textDiv.text(stringendecoder.decodeHtml(user_content))
textDiv.attr('class', 'mid_screen')
contents.push(textDiv)
attrs = [
['user-type', 'output_text'],
['user-title', user_title],
['user-topic', user_topic],
['user-content', user_content]
]
var itemdiv = add_block(2, 2, contents, attrs)
itemdiv.bind(MixIO.actionTags.TEXT_SCREEN_CHANGE, function(event, message) {
MixIO.publish(topic.text(), message)
})
client.on('message', function(topic1, message1) {
if (isAlive && that.isRunning)
if (topic1.split("/")[(isMixly ? 3 : 2)] == topic.text()) {
textDiv.text(message1)
title.parent().parent().attr('user-content', stringendecoder.encodeHtml(String(message1)))
itemdiv.trigger(MixIO.eventTags.TEXT_SCREEN_CHANGED, [String(message1)])
}
})
},
'output_chart': function(user_title, user_topic, user_content, user_style) {
var isAlive = true
var contents = []
var titleDiv = $("<div style='display:flex;flex-direction:row;justify-content:center;align-items:center;margin-top:10px'/>")
var title = $("<h4 class='userTitle'>" + user_title + "</h4>")
titleDiv.append(title)
contents.push(titleDiv)
var topicDiv = $("<div class='topicDiv'/>")
var topic = $("<span class='index-topic' style='color:#858796;margin:0;'>" + user_topic + "</span>")
topicDiv.append($("<i class='fa fa-podcast' style='color:#858796;margin-right:3px'></i>"))
topicDiv.append(topic)
client.on('message', function(topic1, message1) {
if (isAlive && that.isRunning)
if ((topic1.split("/")[(isMixly ? 3 : 2)] == topic.text())) {
var label = (new Date().getHours() + ":" + (new Date().getMinutes() < 10 ? "0" : "") + new Date().getMinutes() + ":" + (new Date().getSeconds() < 10 ? "0" : "") + new Date().getSeconds())
var data = String(message1)
itemdiv.trigger(MixIO.eventTags.LINE_CHART_CHANGED, [label, data])
}
})
attrs = [
['user-type', 'output_chart'],
['user-title', user_title],
['user-topic', user_topic],
['user-content', user_content]
]
var itemdiv = add_block(3, 3, contents, attrs)
itemdiv.addClass("moveDiv")
itemdiv.bind(MixIO.actionTags.LINE_CHART_CHANGE, function(event, value) {
MixIO.publish(topic.text(), value)
})
itemdiv.bind(MixIO.actionTags.LINE_CHART_CLEAR, function() {
})
},
'output_bar': function(user_title, user_topic, user_content, user_style) {
var isAlive = true
var contents = []
var titleDiv = $("<div style='display:flex;flex-direction:row;justify-content:center;align-items:center;margin-top:10px'/>")
var title = $("<h4 class='userTitle'>" + user_title + "</h4>")
titleDiv.append(title)
contents.push(titleDiv)
var topicDiv = $("<div class='topicDiv'/>")
var topic = $("<span class='index-topic' style='margin:0;color:#858796;'>" + user_topic + "</span>")
topicDiv.append($("<i class='fa fa-podcast' style='color:#858796;margin-right:3px'></i>"))
topicDiv.append(topic)
client.on('message', function(topic1, message1) {
if (isAlive && that.isRunning)
if ((topic1.split("/")[(isMixly ? 3 : 2)] == topic.text())) {
var data = String(message1)
itemdiv.trigger(MixIO.eventTags.BAR_CHART_CHANGED, [data])
}
})
attrs = [
['user-type', 'output_bar'],
['user-title', user_title],
['user-topic', user_topic],
['user-content', user_content]
]
var itemdiv = add_block(3, 3, contents, attrs)
itemdiv.bind(MixIO.actionTags.BAR_CHART_CHANGE, function(event, message) {
MixIO.publish(topic.text(), message)
})
itemdiv.bind(MixIO.actionTags.BAR_CHART_CLEAR, function() {
})
},
'output_dashboard': function(user_title, user_topic, user_content, user_style) {
var isAlive = true
var contents = []
var title = $("<h4 class='userTitle'>" + user_title + "</h4>")
contents.push(title)
var topicDiv = $("<div class='topicDiv'/>")
var topic = $("<span class='index-topic' style='margin:0;color:#858796;'>" + user_topic + "</span>")
topicDiv.append($("<i class='fa fa-podcast' style='color:#858796;margin-right:3px'></i>"))
topicDiv.append(topic)
attrs = [
['user-type', 'output_dashboard'],
['user-title', user_title],
['user-topic', user_topic],
['user-content', user_content]
]
var itemdiv = add_block(2, 2, contents, attrs)
client.on('message', function(topic1, message1) {
if (isAlive && that.isRunning)
if (topic1.split("/")[(isMixly ? 3 : 2)] == topic.text()) {
if (!isNaN(parseFloat(message1))) {
itemdiv.trigger(MixIO.eventTags.DASHBOARD_CHANGED, [parseFloat(message1)])
}
}
})
itemdiv.bind(MixIO.actionTags.DASHBOARD_CHANGE, function(event, value) {
MixIO.publish(topic.text(), value)
})
},
'output_map': function(user_title, user_topic, user_content, user_style) {
var isAlive = true
var contents = []
var title = $("<h4 class='userTitle'>" + user_title + "</h4>")
contents.push(title)
var topicDiv = $("<div class='topicDiv'/>")
var topic = $("<span class='index-topic' style='margin:0;color:#858796;'>" + user_topic + "</span>")
topicDiv.append($("<i class='fa fa-podcast' style='color:#858796;margin-right:3px'></i>"))
topicDiv.append(topic)
var mapDiv = $("<div style='width:calc(100% - 20px);height:calc(100% - 60px)'/>")
contents.push(mapDiv)
attrs = [
['user-type', 'output_map'],
['user-title', user_title],
['user-topic', user_topic],
['user-content', user_content]
]
var itemdiv = add_block(2, 2, contents, attrs)
itemdiv.bind(MixIO.actionTags.DATA_MAP_CHANGE, function(event, message) {
MixIO.publish(topic.text(), JSON.stringify(message))
})
itemdiv.bind(MixIO.actionTags.DATA_MAP_CLEAR, function() {
})
client.on('message', function(topic1, message1) {
if (isAlive && that.isRunning)
if (topic1.split("/")[(isMixly ? 3 : 2)] == topic.text()) {
if (isJSON(String(message1)) && JSON.parse(String(message1)).long && JSON.parse(String(message1)).lat && JSON.parse(String(message1)).clientid) {
var jsonMessage = JSON.parse(String(message1))
itemdiv.trigger(MixIO.eventTags.DATA_MAP_CHANGED, [jsonMessage.clientid, jsonMessage.long, jsonMessage.lat, jsonMessage.message])
}
}
})
},
'input_weather': function(user_title, user_topic, user_content, user_style) {
var isAlive = true
var contents = []
var title = $("<h4 class='userTitle'>" + user_title + "</h4>")
contents.push(title)
var topicDiv = $("<div class='topicDiv'/>")
var topic = $("<span class='index-topic' style='margin:0;color:#858796;'>" + user_topic + "</span>")
topicDiv.append($("<i class='fa fa-podcast' style='color:#858796;margin-right:3px'></i>"))
topicDiv.append(topic)
var buttonDiv = $("<div style='margin-top:10px'/>")
var district = ''
var weather_type = ''
var temperature = ''
var humidity = ''
var wind_dir = ''
var wind_class = ''
contents.push(buttonDiv)
attrs = [
['user-type', 'input_weather'],
['user-title', user_title],
['user-topic', user_topic],
['user-content', user_content]
]
var itemdiv = add_block(2, 2, contents, attrs)
var sync_weather = function(){
var dsc_code = title.parent().parent().attr('user-content').split(',')[0].split('w')[0]
if(globalWeather[dsc_code] && globalWeather[dsc_code].time && (new Date().getTime() - globalWeather[dsc_code].time) < 600000) {
var result = globalWeather[dsc_code].data
var resJSON = JSON.parse(result)
weather_type = resJSON.result.now.text
temperature = resJSON.result.now.temp
humidity = resJSON.result.now.rh
wind_dir = resJSON.result.now.wind_dir
wind_class = resJSON.result.now.wind_class
district = resJSON.result.location.name
title.parent().parent().attr('user-content', [title.parent().parent().attr('user-content').split(',')[0], district, weather_type, temperature, humidity, wind_dir, wind_class].join(','))
itemdiv.trigger(MixIO.eventTags.WEATHER_SYNCED, [district, weather_type, temperature, humidity, wind_dir, wind_class])
} else {
http.get('http://api.map.baidu.com/weather/v1/?district_id=' + dsc_code + '&data_type=now&ak=' + configs["BAIDU_MAP_SERVER_AK"], function(req2, res2) {
var html = ''
req2.on('data', function(data) {
html += data;
});
req2.on('end', function() {
globalWeather[dsc_code] = {
time: new Date().getTime(),
data: html
}
var result = html
var resJSON = JSON.parse(result)
if(resJSON.result && resJSON.result.now)
{
weather_type = resJSON.result.now.text
temperature = resJSON.result.now.temp
humidity = resJSON.result.now.rh
wind_dir = resJSON.result.now.wind_dir
wind_class = resJSON.result.now.wind_class
district = resJSON.result.location.name
title.parent().parent().attr('user-content', [title.parent().parent().attr('user-content').split(',')[0], district, weather_type, temperature, humidity, wind_dir, wind_class].join(','))
itemdiv.trigger(MixIO.eventTags.WEATHER_SYNCED, [district, weather_type, temperature, humidity, wind_dir, wind_class])
}
});
})
}
}
itemdiv.bind(MixIO.actionTags.WEATHER_SYNC, function() {
sync_weather()
})
sync_weather()
itemdiv.bind(MixIO.actionTags.WEATHER_SEND, function() {
var weather = {
'district': district,
'weather_type': weather_type,
'temperature': temperature,
'humidity': humidity,
'wind_dir': wind_dir,
'wind_class': wind_class
}
MixIO.publish(topic.text(), JSON.stringify(weather))
itemdiv.trigger(MixIO.eventTags.WEATHER_SENT, [district, weather_type, temperature, humidity, wind_dir, wind_class])
})
},
'trigger': function() {
//Removed
},
'table': function(user_title, user_topic, user_content, user_style) {
var isAlive = true
client.on('message', function(topic1, message1) {
if (isAlive && that.isRunning)
if (topic1.split("/")[(isMixly ? 3 : 2)] == topic.text()) {
var message = String(message1).split(',')
itemdiv.trigger(MixIO.eventTags.DATA_TABLE_CHANGED, [message])
}
})
var contents = []
var title = $("<h4 class='userTitle'>" + user_title + "</h4>")
contents.push(title)
var topicDiv = $("<div class='topicDiv'/>")
var topic = $("<span class='index-topic' style='margin:0;color:#858796;'>" + user_topic + "</span>")
topicDiv.append($("<i class='fa fa-podcast' style='color:#858796;margin-right:3px'></i>"))
topicDiv.append(topic)
attrs = [
['user-type', 'table'],
['user-title', user_title],
['user-topic', user_topic],
['user-content', user_content]
]
var itemdiv = add_block(3, 3, contents, attrs)
itemdiv.bind(MixIO.actionTags.DATA_TABLE_CHANGE, function(event, message) {
MixIO.publish(topic.text(), message)
})
itemdiv.bind(MixIO.actionTags.DATA_TABLE_CLEAR, function() {
})
},
'decorate_text': function() {},
'decorate_pic': function() {}
}
for (var ct = 0; ct <= units_array.length - 1; ct = ct + 1) {
var un = $(units_array[ct])
toolkits[un.attr('user-type')](un.attr('user-title'), un.attr('user-topic'), un.attr('user-content'), un.attr('style'))
}
}()
}
function Uint8ArrayToString(fileData) {
var dataString = "";
for (var i = 0; i < fileData.length; i++) {
dataString += String.fromCharCode(fileData[i]);
}
return dataString;
}
function timeStamp2String() {
var datetime = new Date();
var year = datetime.getFullYear();
var month = datetime.getMonth() + 1 < 10 ? "0" + (datetime.getMonth() + 1) : datetime.getMonth() + 1;
var date = datetime.getDate() < 10 ? "0" + datetime.getDate() : datetime.getDate();
var hour = datetime.getHours() < 10 ? "0" + datetime.getHours() : datetime.getHours();
var minute = datetime.getMinutes() < 10 ? "0" + datetime.getMinutes() : datetime.getMinutes();
var second = datetime.getSeconds() < 10 ? "0" + datetime.getSeconds() : datetime.getSeconds();
return year + "-" + month + "-" + date + " " + hour + ":" + minute + ":" + second;
}
function isJSON(str) {
if (typeof str == 'string') {
try {
var obj = JSON.parse(str);
if (typeof obj == 'object' && obj) {
return true;
} else {
return false;
}
} catch (e) {
return false;
}
}
}
1
https://gitee.com/mixly2/mixio.git
git@gitee.com:mixly2/mixio.git
mixly2
mixio
mixio
master

搜索帮助