8 Star 42 Fork 5

mixly2/mixio

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
mixio.js 156.73 KB
一键复制 编辑 原始数据 按行查看 历史
宋义深 提交于 2024-10-15 21:17 . fix-lang-bug
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523
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');
const path = require('path');
var readline = require('readline');
var iconv = require('iconv-lite');
var request = require('request');
const cors = require('cors');
var globalQPSControl = {}
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-----
MIID0TCCArmgAwIBAgICYxswDQYJKoZIhvcNAQELBQAwczELMAkGA1UEBhMCQ04x
EDAOBgNVBAgMB1RpYW5qaW4xEDAOBgNVBAcMB1RpYW5qaW4xFTATBgNVBAoMDENI
SU5BU1NMIEluYzEpMCcGA1UEAwwgQ0hJTkFTU0wgQ2VydGlmaWNhdGlvbiBBdXRo
b3JpdHkwHhcNMjQwOTI5MTUyMDI4WhcNMjUwOTI5MTUyMDI4WjB3MQswCQYDVQQG
EwJDTjEOMAwGA1UECAwFTWl4bHkxDjAMBgNVBAoMBU1peGx5MQ4wDAYDVQQLDAVN
aXhseTEWMBQGA1UEAwwNZXhhbXBsZS5taXhseTEgMB4GCSqGSIb3DQEJARYRZXhh
bXBsZUBtaXhseS52b20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDA
EMX1qHnw4026dMFrNTuzwdZiSl8ojgzrMVj+sy287hismsj3YDNlkwdhTUGbvqwR
YOBB5pupHMeKUL22UU3czHbvwghTC4S+Y7kQG16uFXm8Nxik1KYXyV0IuYd8Db8I
u1SDH09wN4+JralpTqCRT94hrFpODbLwWldhgQadVuhh0IfkJowZS7/PehwlXFwI
vNg9i7XJFLTqJYvnm7vG95lfCwqf3bAjcuwoM52vtbVQ4OK0O0NKnIuDmpn8kLSH
nro4yYZvcDwp2u2Pm5jMx8R4XpRgoNliOYhqGOUSEckvN1k4dgfM8I2OHszEVLKM
c2Y73v7s4V9cuSRlS9Q5AgMBAAGjazBpMB8GA1UdIwQYMBaAFFwfI/rI4SExwtg3
9oj80m/CVEMzMAkGA1UdEwQCMAAwCwYDVR0PBAQDAgTwMC4GA1UdEQQnMCWCCWxv
Y2FsaG9zdIIMd3d3LnRlc3QuY29thwTAqAABhwR/AAABMA0GCSqGSIb3DQEBCwUA
A4IBAQAroAByalkB/CtXPXH+coWAJGlwJf16p8fHvQzZsY4ENIwZn/C5y5GTIST+
BQs3ScHOlox2WrVEK2AsIrwt/Kyr2gGLw/qDdpPP3HZIgFFl0FII7OrRyVI5wu3C
6z+I/KorzvZX07eVevMc/S02zsmt2RdWpfdf+kZXn9lvVkrUfsvfP69cUxiO0qmh
D/GvjSoGgz2k6aPa9hC8nu8EwAs4I3dY7NGQFED+xa+L7lL0Bp5AKqlQB9GMYaJ6
bTz4wxPbQbAeCHlF0MIIM5V8imnyIzGJGBNAnZxy+Wkd2+NZXqSTvo1aPxJnhOHC
EljElgZJBd+WCYFPEtdruklvlE93
-----END CERTIFICATE-----
`
fs.writeFileSync("config/certs/file.crt", defaultCrt)
var defaultPem =
`-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDAEMX1qHnw4026
dMFrNTuzwdZiSl8ojgzrMVj+sy287hismsj3YDNlkwdhTUGbvqwRYOBB5pupHMeK
UL22UU3czHbvwghTC4S+Y7kQG16uFXm8Nxik1KYXyV0IuYd8Db8Iu1SDH09wN4+J
ralpTqCRT94hrFpODbLwWldhgQadVuhh0IfkJowZS7/PehwlXFwIvNg9i7XJFLTq
JYvnm7vG95lfCwqf3bAjcuwoM52vtbVQ4OK0O0NKnIuDmpn8kLSHnro4yYZvcDwp
2u2Pm5jMx8R4XpRgoNliOYhqGOUSEckvN1k4dgfM8I2OHszEVLKMc2Y73v7s4V9c
uSRlS9Q5AgMBAAECggEBAKNfISQe1OrETl+l5MiOlWQII5Wj8WGLww1kAnFUdDla
xf48A2n4mH90Gzj3ADG8dJyrrNYhlJK6+jh7CYRFkFeaTCkRAQeyqo1QQiCjR1wI
xG4G5519jHJ7Q/mh5s7s2mxQ/Eg0n9uyRxQzdgEvcoFoUGiQNJhkKqssDVvQ5pF5
3CGCOx9Rt6cX+BWdZyV46HBtBSpkx+0kETIpv1YBvo6JKubrcf8zTMXI8tEZ12qU
LDybZvl6JrUXD0QL+I1uhDIsRYIGbTZZRMOpukhyXuMGu/O249z/gI9WtdTzCQLU
YUNxwK6TezmzJMGrZgD+bJxFJSiHufIw9ROaWE2F30kCgYEA3kOf24WGUxlzwGvj
IJMoFOIlQ3xXlazRS09HmlSIeTJiBOtPQlvJHv+I9rBHRNVTz7mRJpmRZIq4Nkbo
miFrGbwu2eqa+q/CCxfbrv8ZFV9OJYD0v4mSgLarDgctfhC3iUkaQMFqD24L6T+1
ENPCpeV6H73Ize8ecn01bGoTRJMCgYEA3Te9Yun4L/6t1dS8dhH16ALsBCWuta47
nQJ2xrrZMWdxlESbLqbmV2bE7u3I+/yKoF0hFFFASxNCxpP/ZQRcsfIXrcL7SmW5
nwzz1mSWInN7xltWSegKhxNdAUDeWfINznPaho7s/eKY7ogla9ShFhc6Xl+uj2+e
Iq6/Vfb8b4MCgYEAyKoFCQvj2eKAvpio1iAFb9U8D1GTQW5lBrjszEjFbaYvGIHZ
bO+xBGtwHEfKEDsJD+FZSqAaw8r5xQb/uSeyqelb4yIMCYfkiF9h1vw4iTMiOnnS
fZqWyd4hUOjqCYbOLQPyz8PPHV8dIdiCgE6uzVgAieeuAz5/Hp4sPVUHUEECgYA7
8eHJDvupDctPWWFkYUOQhlIsYYWxR7BxwHwtJ+64+34Enn6qqqFaZ8fPsvG2jt2F
zRasqcPRVDvREcOwPPldYuvVszNjGqOtHNZqb0Fbvo1418FPL6jCp5WZRFm8Z+Ij
4rMBqXNA7QliAdSaHrk0AkFX13e2+JkSbuX8RnxrPwKBgHVMwcjNJe19sXb/F4l3
ag7Z9uRvToDKyCZ73WHFDUItJcCAITuZpxAdaJdtCFWGHdu26rza/H7wEgKN/Lem
HKqIhewfd473iyVbGW5PfCPXEH4oJI5NLbd2MvUJPi8oSHupmc+JbkD8n2uMU7s3
mUGpI4CFOgtRwpo9KRebaqfq
-----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('/api/v1/getData', function(req, res) {
try{
if(!(req.query.user && req.query.password && req.query.project && req.query.topic))
{
res.send('{"status":"incorrect params"}')
return
}
var user = req.query.user
var password = req.query.password
var project = req.query.project
var topic = req.query.topic
var num = 1
if(globalQPSControl[user])
{
if(Date.now() - globalQPSControl[user] > 1000)
{
globalQPSControl[user] = Date.now()
}
else{
res.send('{"status":"too fast"}')
return
}
}
else
globalQPSControl[user] = Date.now()
if (req.query.num)
num = req.query.num
db.get("select password from user where username = ?", [user], function(err, row) {
if (err)
{
res.send('{"status":"failed"}')
}
else if ((!row) && (password!="MixIO_public" || user[0]!="@"))
{
res.send('{"status":"failed"}')
}
else if ( ((!row) && (password=="MixIO_public" && user[0]=="@")) || (row && (row["password"] == password)) ) {
db.get("select * from project where username = ? and projectName = ?", [user, project], function(err, row) {
if (err)
{
res.send('{"status":"failed"}')
}
else if (row) {
var dataStorage = row["dataStorage"]
if (dataStorage == null)
dataStorage = "{}"
var dataStorageJSON = JSON.parse(dataStorage)
if(dataStorageJSON["received"] && dataStorageJSON["received"][topic])
{
var data = dataStorageJSON["received"][topic]
if(data.length<num)
num = data.length
data = data.slice(0,num)
for(var i = 0;i<data.length;i++)
{
// for each key, if value is int, convert to int; if value is float, convert to float
for(var key in data[i])
{
// if only have digits, convert to int
if(/^\d+$/.test(data[i][key]))
data[i][key] = parseInt(data[i][key])
// if have digits and one dot, convert to float
else if(/^\d+\.\d+$/.test(data[i][key]))
data[i][key] = parseFloat(data[i][key])
// if json string, convert to json
else if(data[i][key].startsWith("{") && data[i][key].endsWith("}"))
try{
data[i][key] = JSON.parse(stringendecoder.decodeHtml(data[i][key]))
for(var key2 in data[i][key])
{
if(/^\d+$/.test(data[i][key][key2]))
data[i][key][key2] = parseInt(data[i][key][key2])
else if(/^\d+\.\d+$/.test(data[i][key][key2]))
data[i][key][key2] = parseFloat(data[i][key][key2])
}
}
catch(e){
data[i][key] = data[i][key]
}
}
}
res.send(JSON.stringify({
"status": "success",
"data": data
}))
}
else
res.send('{"status":"success","data":[]}')
}
})
}
else
{
res.send('{"status":"failed"}')
}
})
}
catch(e){
res.send('{"status":"failed"}')
}
})
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 {
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(1)
var instance = this.$("[" + "user-title='" + name + "']")
if (instance.length != 1)
throw new MixIOLogicError(2)
if (instance.attr("user-type") != this.oldTags[type - 1])
throw new MixIOLogicError(3)
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;
}
}
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/mixly2/mixio.git
git@gitee.com:mixly2/mixio.git
mixly2
mixio
mixio
master

搜索帮助