Commit 299e5fbe authored by nextime's avatar nextime

Add tables and support for syncing board configs in daemon

parent 6295d491
CREATE TABLE IF NOT EXISTS `ioconf_analogs` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`boardname` varchar(255) NOT NULL,
`boardip` varchar(15) NOT NULL,
`ananum` smallint(6) NOT NULL DEFAULT '1',
`status_num` enum('1','2','3','4') NOT NULL DEFAULT '1',
`status_name` varchar(32) NOT NULL DEFAULT 'DEFAULT',
`enabled` enum('yes','no') NOT NULL DEFAULT 'no',
`anatype` int(5) unsigned NOT NULL DEFAULT '0',
`mintime` int(5) unsigned NOT NULL DEFAULT '1',
`minval` int(11) NOT NULL DEFAULT '0',
`maxval` int(11) NOT NULL DEFAULT '1023',
`continuos_domain` varchar(32) NOT NULL,
`continuos_msg` int(5) unsigned NOT NULL DEFAULT '0',
`continuos_ctx` int(5) unsigned NOT NULL DEFAULT '0',
`continuos_act` int(5) unsigned NOT NULL DEFAULT '0',
`continuos_time` int(6) NOT NULL DEFAULT '1',
`continuos_opt` int(5) unsigned NOT NULL DEFAULT '0',
`continuos_optstring` varchar(64) NOT NULL,
`continuos_dst` varchar(15) NOT NULL DEFAULT '0.0.0.0',
`min_domain` varchar(32) NOT NULL,
`min_msg` int(5) unsigned NOT NULL DEFAULT '0',
`min_ctx` int(5) unsigned NOT NULL DEFAULT '0',
`min_act` int(5) unsigned NOT NULL DEFAULT '0',
`min_level` int(6) NOT NULL DEFAULT '1',
`min_opt` int(5) unsigned NOT NULL DEFAULT '0',
`min_optstring` varchar(64) NOT NULL,
`min_dst` varchar(15) NOT NULL DEFAULT '0.0.0.0',
`max_domain` varchar(32) NOT NULL,
`max_msg` int(5) unsigned NOT NULL DEFAULT '0',
`max_ctx` int(5) unsigned NOT NULL DEFAULT '0',
`max_act` int(5) unsigned NOT NULL DEFAULT '0',
`max_level` int(6) NOT NULL DEFAULT '1',
`max_opt` int(5) unsigned NOT NULL DEFAULT '0',
`max_optstring` varchar(64) NOT NULL,
`max_dst` varchar(15) NOT NULL DEFAULT '0.0.0.0',
PRIMARY KEY (`id`),
KEY `enables` (`enabled`),
KEY `boardname` (`boardname`),
KEY `boardip` (`boardip`),
KEY `status_num` (`status_num`),
KEY `status_name` (`status_name`),
KEY `anatype` (`anatype`),
KEY `ananum` (`ananum`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
CREATE TABLE IF NOT EXISTS `ioconf_inputs` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`boardname` varchar(255) NOT NULL,
`boardip` varchar(15) NOT NULL,
`inpnum` smallint(6) NOT NULL DEFAULT '0',
`status_num` enum('1','2','3','4') NOT NULL DEFAULT '1',
`status_name` varchar(32) NOT NULL DEFAULT 'DEFAULT',
`enabled` enum('yes','no') NOT NULL DEFAULT 'no',
`inptype` int(5) unsigned NOT NULL DEFAULT '0',
`mintime` int(5) unsigned NOT NULL DEFAULT '1',
`act1_domain` varchar(32) NOT NULL,
`act1_msg` int(5) unsigned NOT NULL DEFAULT '0',
`act1_ctx` int(5) unsigned NOT NULL DEFAULT '0',
`act1_act` int(5) unsigned NOT NULL DEFAULT '0',
`act1_time` int(6) NOT NULL DEFAULT '1',
`act1_opt` int(5) unsigned NOT NULL DEFAULT '0',
`act1_optstring` varchar(64) NOT NULL,
`act1_dst` varchar(15) NOT NULL DEFAULT '0.0.0.0',
`act2_domain` varchar(32) NOT NULL,
`act2_msg` int(5) unsigned NOT NULL DEFAULT '0',
`act2_ctx` int(5) unsigned NOT NULL DEFAULT '0',
`act2_act` int(5) unsigned NOT NULL DEFAULT '0',
`act2_level` int(6) NOT NULL DEFAULT '1',
`act2_opt` int(5) unsigned NOT NULL DEFAULT '0',
`act2_optstring` varchar(64) NOT NULL,
`act2_dst` varchar(15) NOT NULL DEFAULT '0.0.0.0',
`act3_domain` varchar(32) NOT NULL,
`act3_msg` int(5) unsigned NOT NULL DEFAULT '0',
`act3_ctx` int(5) unsigned NOT NULL DEFAULT '0',
`act3_act` int(5) unsigned NOT NULL DEFAULT '0',
`act3_level` int(6) NOT NULL DEFAULT '1',
`act3_opt` int(5) unsigned NOT NULL DEFAULT '0',
`act3_optstring` varchar(64) NOT NULL,
`act3_dst` varchar(15) NOT NULL DEFAULT '0.0.0.0',
PRIMARY KEY (`id`),
KEY `enables` (`enabled`),
KEY `boardname` (`boardname`),
KEY `boardip` (`boardip`),
KEY `status_num` (`status_num`),
KEY `status_name` (`status_name`),
KEY `anatype` (`inptype`),
KEY `inpnum` (`inpnum`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
CREATE TABLE IF NOT EXISTS `ioconf_outputs` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`boardname` varchar(255) NOT NULL,
`boardip` varchar(15) NOT NULL,
`outnum` smallint(6) NOT NULL DEFAULT '0',
`enabled` enum('yes','no') NOT NULL DEFAULT 'no',
`outtype` int(5) unsigned NOT NULL DEFAULT '0',
`ctx` int(5) unsigned NOT NULL DEFAULT '0',
`startime` int(5) unsigned NOT NULL DEFAULT '50',
`opentime` int(5) unsigned NOT NULL DEFAULT '300',
`pausetime` int(5) NOT NULL DEFAULT '50',
`bang` enum('yes','no') NOT NULL DEFAULT 'no',
`r1_relay` int(5) unsigned NOT NULL DEFAULT '0',
`r1_def` enum('NC','NO','SAVE') NOT NULL DEFAULT 'NO',
`r1_duration` int(5) unsigned NOT NULL DEFAULT '0',
`r1_retard` int(5) unsigned NOT NULL DEFAULT '0',
`r1_tollerance` int(5) unsigned NOT NULL DEFAULT '0',
`r1_rearm` int(5) unsigned NOT NULL DEFAULT '0',
`r1_ampere` int(3) unsigned NOT NULL DEFAULT '80',
`r2_relay` int(5) unsigned NOT NULL DEFAULT '0',
`r2_def` enum('NC','NO','SAVE') NOT NULL DEFAULT 'NO',
`r2_duration` int(5) unsigned NOT NULL DEFAULT '0',
`r2_retard` int(5) unsigned NOT NULL DEFAULT '0',
`r2_tollerance` int(5) unsigned NOT NULL DEFAULT '0',
`r2_rearm` int(5) unsigned NOT NULL DEFAULT '0',
`r2_ampere` int(3) unsigned NOT NULL DEFAULT '80',
PRIMARY KEY (`id`),
KEY `enables` (`enabled`),
KEY `boardname` (`boardname`),
KEY `boardip` (`boardip`),
KEY `anatype` (`outtype`),
KEY `outnum` (`outnum`),
KEY `ctx` (`ctx`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
CREATE TABLE IF NOT EXISTS `ioconf_pwm` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
......@@ -30,7 +30,10 @@
<div class="panel col-lg-4">
<div class="panel-heading">
<h3 class="panel-title">Boards <a data-toggle="modal" href="#AutoDetect" class="btn btn-danger btn-small pull-right" style="padding:3px;">Autodetect</a></h3>
<h3 class="panel-title">Boards
<a data-toggle="modal" data-dmboard="lock" href="#AutoDetect" class="btn btn-danger btn-small pull-right" style="padding:3px;margin-left:5px;">Autodetect</a>
<a data-toggle="modal" data-dmboard="lock" href="#Sync" class="btn btn-danger btn-small pull-right" style="padding:3px;">Sync I/O Config</a>
</h3>
</div>
<div class="home-panel">
<table class="table table-condensed">
......@@ -55,6 +58,14 @@
<td><?=$board['type']?></td>
<td><?=$board['fwversion']?></td>
<td><?=$board['fwtype']?></td>
<td>
<!--
<button style="margin-left:5px;" type="button" class="btn btn-success btn-small pull-right">Edit</button>
-->
<button style="margin-left:5px;" type="button" data-dmact="sync" data-boardid="<?=$board['id']?>" class="btn btn-danger btn-small pull-right">Sync</button>
<button style="margin-left:5px;" type="button" data-dmact="push" data-boardid="<?=$board['id']?>" class="btn btn-info btn-small pull-right">Push</button>
<img src="/resources/preloader/images/animated.gif" data-dmboardload="<?=$board['id']?>" style="height:30px;width:30px;display:none" class="pull-right"></img>
</td>
</tr>
<?
}
......@@ -86,6 +97,27 @@
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
<div class="modal fade" id="Sync" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title">Board IOConf Sync</h4>
</div>
<div class="modal-body">
<b>WARNING: </b>you are starting Domotika Boards I/O Sync procedure. This will
delete any saved board I/O Config in the Domotika database and then
they will be re-loaded from the Domotika boards.
Any change will be losed.
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default pull-left" data-dismiss="modal" >Discard</button>
<button type="button" class="btn btn-danger" data-dismiss="modal" id="startsync">Start Syncing</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
<div class="panel col-lg-4">
<div class="panel-heading">
......@@ -213,6 +245,39 @@
</div> <!-- container -->
<?include("parts/foot.php");?>
<script type="text/javascript">
function lockGlobalBoards()
{
$("[data-dmboard=lock]").each(
function(){
$(this).attr("disabled","true");
}
);
}
function lockAllBoards()
{
$("[data-dmact=sync]").each(
function(){
$(this).attr("disabled","true");
}
);
$("[data-dmact=push]").each(
function(){
$(this).attr("disabled","true");
}
);
$("[data-dmboardload]").each(
function(){
$(this).css("display","block");
}
);
lockGlobalBoards();
}
$("#startdetection").click(
function() {
if($('#forcedetect').is(":checked"))
......@@ -221,6 +286,49 @@
$.get("/rest/v1.2/boards/autodetect/json");
}
);
$("#startsync").click(
function() {
lockAllBoards();
$.get("/rest/v1.2/boards/syncall/json");
}
);
$("[data-dmact=push]").click(
function() {
$("[data-dmboardload="+$(this).attr('data-boardid')+"]").each(
function(){
$(this).css("display","block");
}
);
$(this).attr('disabled', true);
$("[data-dmact=sync][data-boardid="+$(this).attr('data-boardid')+"]").each(
function() {
$(this).attr('disabled', true);
}
);
lockGlobalBoards();
$.get("/rest/v1.2/boards/pushboardbyid/"+$(this).attr('data-boardid')+"/json");
}
)
$("[data-dmact=sync]").click(
function() {
$("[data-dmboardload="+$(this).attr('data-boardid')+"]").each(
function(){
$(this).css("display","block");
}
);
$(this).attr('disabled', true);
$("[data-dmact=push][data-boardid="+$(this).attr('data-boardid')+"]").each(
function() {
$(this).attr('disabled', true);
}
);
lockGlobalBoards();
$.get("/rest/v1.2/boards/syncboardbyid/"+$(this).attr('data-boardid')+"/json");
}
)
</script>
</body>
</html>
......@@ -24,7 +24,37 @@
}
var unlockBoards = function(event) {
var data=$.parseJSON(event.data);
$("[data-dmact=sync][data-boardid="+data.data+"],[data-dmact=push][data-boardid="+data.data+"]").each(
function() {
$(this).attr("disabled", false);
}
);
$("[data-dmboardload="+data.data+"]").each(
function(){
$(this).css("display","none");
}
);
var loaders=false;
$("[data-dmboardload]").each(
function(){
if($(this).css("display")=="block")
loaders=true;
}
);
if(loaders==false)
{
$("[data-dmboard=lock]").each(
function(){
$(this).attr("disabled",false);
}
);
}
}
es.addEventListener("daemonstatus", setDaemonStatus);
es.addEventListener("boardOK", unlockBoards);
es.onerror = function(event){
if(es.readystate=='CLOSED')
......
......@@ -31,7 +31,12 @@ from dmlib import constants as C
from twisted.web import microdom as xml
from domotika.lang import lang
from iotype import BoardAnalog, BoardInput, BoardOutput, BoardRelay
from twisted.web import error
from dmlib.utils.pwgen import GeneratePwd
from dmlib.utils import genutils
from twisted.internet import reactor
from domotika.db import dmdb
import urllib
log = logging.getLogger( 'Core' )
......@@ -45,6 +50,41 @@ except:
import sha1
# i_[idx]_[ananum+totinp]_[statusnum]_[act]
ANAINDEX={
'status_name': ['09', '00'],
'enabled': ['05', '00'],
'anatype': ['11', '00'],
'mintime': ['06', '00'],
'minval': ['12', '00'],
'maxval': ['13', '00'],
'continuos_domain': ['02','01'],
'continuos_msg': ['07','01'],
'continuos_ctx': ['03','01'],
'continuos_act': ['01','01'],
'continuos_time': ['10','01'],
'continuos_opt': ['14','01'],
'continuos_optstring': ['15','01'],
'continuos_dst': ['04','01'],
'min_domain': ['02','02'],
'min_msg': ['07','02'],
'min_ctx': ['03','02'],
'min_act': ['01','02'],
'min_level': ['10','02'],
'min_opt': ['14','02'],
'min_optstring': ['15','02'],
'min_dst': ['04','02'],
'max_domain': ['02','03'],
'max_msg': ['07','03'],
'max_ctx': ['03','03'],
'max_act': ['01','03'],
'max_level': ['10','03'],
'max_opt': ['14','03'],
'max_optstring': ['15','03'],
'max_dst': ['04','03'],
}
def context2section(ctx):
if int(ctx) in C.SECTIONS.keys():
section=C.SECTIONS[int(ctx)]
......@@ -74,7 +114,14 @@ class BaseBoard(object):
numAna = 2
numInp = 12
numOut = 12
initialized = False
boardid = False
analogLock = False
inputLock = False
outputLock = False
pwmLock = False
def __init__(self, core, host, port, pwd, lang):
#self.fwtype = 'relaymaster'
self.host = host
......@@ -83,13 +130,35 @@ class BaseBoard(object):
self.lang = lang
self.core = core
def endinit(self, res):
self.initialized=True
return res
def initialize(self):
d=self._getBoardConfig()
d.addCallback(self._setBoardConfig)
d.addCallback(self._getIOConfig)
d.addCallback(self._setIOConfig)
d.addCallback(self._configComplete)
return d
return d.addCallback(self.endinit)
def sendUnLock(self):
def _send(res):
if res:
return self.core.boardOK(res.id)
if (not self.analogLock
and not self.inputLock
and not self.outputLock
and not self.pwmLock):
boardname=str(xml.getElementsByTagName(self.boardXML, 'cfg_hostname')[0].firstChild().toxml())
boardip=str(xml.getElementsByTagName(self.boardXML, 'cfg_ip')[0].firstChild().toxml())
log.info("Unlocking board module "+str(boardname)+" at "+str(boardip))
if not self.boardid:
return dmdb.DMBoards.find(where=["name='%s' and ip='%s'" %(boardname, boardip)], limit=1).addCallback(_send)
return self.core.boardOK(boardid)
def _configComplete(self, *a):
return defer.succeed(self)
......@@ -111,8 +180,34 @@ class BaseBoard(object):
def _getIOConfig(self, *a):
return self.requestPage("http://"+self.host+":"+str(self.port)+"/ioconf.xml")
def requestPage(self, uri):
return wu.getPage(uri, http_user=self.user, http_password=self.pwd)
def _requestPageErr(self, err, uri=False, method='GET', postdata=None, nolocation=False, second=False):
if err.getErrorMessage().split()[0] == '401' and not second:
log.info('Board '+str(self.host)+' doesn\'t appears to support SETOTP command for uri '+str(uri))
return wu.getPage(uri, http_user=self.user, http_password=self.pwd,
method=method, postdata=postdata).addErrback(self._requestPageErr, uri, nolocation=nolocation, second=True)
log.error("Page "+str(uri)+"can't be accessed! ("+err.getErrorMessage()+")")
raise error.Error(err.getErrorMessage().split()[0], err.getErrorMessage())
def _requestPageOk(self, res, uri):
log.info('Board '+str(self.host)+' OTP Request OK for uri '+str(uri))
return res
def _requestOTPPage(self, uri, pwd, method='GET', postdata=None, nolocation=False):
log.info("Send OTP Request for "+str(uri)+" with pwd "+str(pwd))
return wu.getPage(uri, http_user='otp', http_password=str(pwd), method=method, postdata=postdata, nolocation=nolocation
).addCallback(self._requestPageOk, uri
).addErrback(self._requestPageErr, uri, method, postdata, nolocation)
def _requestPage(self, res, uri, pwd, method='GET', postdata=None, nolocation=False):
return self._requestOTPPage(uri, pwd, method, postdata, nolocation)
def requestPage(self, uri, method='GET', postdata=None, nolocation=False):
pwd=GeneratePwd(leng=16)
self.core.setOTP(pwd, self.host)
d=defer.Deferred()
d.addCallback(self._requestPage, uri, pwd, method, postdata, nolocation)
reactor.callLater(.5, d.callback, True)
return d
def getAnalogsNames(self):
return {}
......@@ -145,9 +240,139 @@ class ANABoard(object):
return ret
return self.analist
def syncAnalogs(self):
if self.analogLock:
return
self.analogLock=True
if not self.initialized:
self.initialize().addCallback(
self._ioAnalogsDelete).addCallback(
self._syncAnalogs)
else:
self._ioAnalogsDelete().addCallback(
self._syncAnalogs)
def _ioAnalogsDelete(self, res=None):
boardname=str(xml.getElementsByTagName(self.boardXML, 'cfg_hostname')[0].firstChild().toxml())
boardip=str(xml.getElementsByTagName(self.boardXML, 'cfg_ip')[0].firstChild().toxml())
return dmdb.runOperation("DELETE FROM ioconf_analogs WHERE boardname='%s' AND boardip='%s'" %(str(boardname), str(boardip)))
def _syncAnalogs(self, res=None):
boardname=str(xml.getElementsByTagName(self.boardXML, 'cfg_hostname')[0].firstChild().toxml())
boardip=str(xml.getElementsByTagName(self.boardXML, 'cfg_ip')[0].firstChild().toxml())
log.info("Syncing board "+str(boardname)+" at "+str(boardip))
for i in [self.firstAna, self.firstAna+self.numAna-1]:
aname=xml.getElementsByTagName(self.ioXML, 'i'+str(i))[0].firstChild().toxml()
for n in xrange(1, 5):
sconf=str(xml.getElementsByTagName(self.ioXML, 'i'+str(i)+'s'+str(n))[0].firstChild().toxml()).split(';')
d=dmdb.IOConfAnalogs()
d.boardname=boardname
d.boardip=boardip
d.ananum=i-self.firstAna+1
d.status_num=n
d.status_name=sconf[0]
d.enabled='yes' if sconf[2]=='1' else 'no'
d.anatype=int(sconf[3])
d.mintime=int(sconf[1])
d.minval=int(sconf[28])
d.maxval=int(sconf[29])
d.continuos_domain=str(sconf[4])
d.continuos_msg=int(sconf[8])
d.continuos_ctx=int(sconf[7])
d.continuos_act=int(sconf[9])
d.continuos_time=int(sconf[6])
d.continuos_opt=int(sconf[10])
d.continuos_optstring=str(sconf[11])
d.continuos_dst=str(sconf[5])
d.min_domain=str(sconf[12])
d.min_msg=int(sconf[16])
d.min_ctx=int(sconf[15])
d.min_act=int(sconf[17])
d.min_level=int(sconf[14])
d.min_opt=int(sconf[18])
d.min_optstring=str(sconf[19])
d.min_dst=str(sconf[13])
d.max_domain=str(sconf[20])
d.max_msg=int(sconf[24])
d.max_ctx=int(sconf[23])
d.max_act=int(sconf[25])
d.max_level=int(sconf[22])
d.max_opt=int(sconf[26])
d.max_optstring=str(sconf[27])
d.max_dst=str(sconf[21])
d.save()
self.analogLock=False
self.sendUnLock()
def pushAnalogs(self, ananum=False, status='*', dataonly=False, bname=False):
if self.analogLock:
return
if genutils.is_number(status) and int(status) in [1,2,3,4]:
s=int(status)
else:
s=str(status)
if not ananum or ananum=='*':
self._pushAnalog(1, s, dataonly, bname).addCallback(lambda x: self._pushAnalog(2, s, dataonly, bname))
else:
if genutils.is_number(ananum) and int(ananum) in [1,2]:
self._pushAnalog(int(ananum), s, dataonly, bname)
def _sendAnalogIOConf(self, res, dataonly=False):
def endPush(res):
log.info("Push for "+str(uri)+" finished")
self.analogLock=False
self.sendUnLock()
return defer.succeed(True)
def normalize(v):
if v in ['yes','no']:
return '1' if v=='yes' else '0'
return urllib.quote(str(a[k]))
postdata=""
for ana in res:
if dataonly:
if type(dataonly).__name__!='list':
dataonly=str(dataonly).replace(" ","").split(",")
else:
dataonly=ANAINDEX.keys()
a=ana.__dict__
for k in dataonly:
if k in a.keys():
if len(postdata)>0:
postdata+="&"
postdata+="i_"+ANAINDEX[k][0]+"_"+str(a['ananum']+self.firstAna-1).zfill(2)+"_"
postdata+=str(a['status_num']).zfill(2)+"_"+ANAINDEX[k][1]+"="
postdata+=normalize(a[k])
uri="http://"+self.host+":"+str(self.port)+"/ioconf.xml"
log.info("Posting Analog config to "+str(uri))
return self.requestPage(uri, method='POST', postdata=postdata, nolocation=True).addCallbacks(endPush, endPush)
def _getAnalogIOConf(self, res, num, status, dataonly=False, bname=False):
boardname=bname
boardip=self.host
if not bname:
boardname=str(xml.getElementsByTagName(self.boardXML, 'cfg_hostname')[0].firstChild().toxml())
#sqlstring="SELECT * FROM ioconf_analogs WHERE boardname='%s' AND boardip='%s'" % (boardname, boardip)
sqlstring="boardname='%s' AND boardip='%s'" % (boardname, boardip)
if genutils.is_number(status) and status != '*':
sqlstring+=" AND status_num='%s'" % str(status)
elif status!='*':
sqlstring+=" AND DMDOMAIN(status, '%s')=1"
#dmdb.runQuery(sqlstring).addCallback(self._sendAnalogIOConf, dataonly)
return dmdb.IOConfAnalogs.find(where=[sqlstring]).addCallback(self._sendAnalogIOConf, dataonly)
def _pushAnalog(self, num, status, dataonly=False, bname=False):
self.analogLock=True
if not bname and not self.initialized:
return self.initialize().addCallback(self._getAnalogIOConf, num, status, dataonly, bname)
return self._getAnalogIOConf(True, num, status, dataonly, bname)
class INPBoard(object):
def getInputsNames(self):
if not self.inplist:
ret = {}
......@@ -164,6 +389,12 @@ class INPBoard(object):
return ret
return self.inplist
def syncInputs(self):
pass
def pushInputs(self, inpnum=False, status=1):
pass
class OUTBoard(object):
......@@ -295,3 +526,8 @@ class OUTBoard(object):
self.outlist = ret
return self.outlist
def syncOutputs(self):
pass
def pushOutputs(self, numout=False):
pass
......@@ -106,6 +106,18 @@ def dbset():
global store
Registry.DBPOOL = store
class IOConfInputs(DBObject):
TABLENAME="ioconf_inputs"
class IOConfAnalogs(DBObject):
TABLENAME="ioconf_analogs"
class IOConfOutput(DBObject):
TABLENAME="ioconf_outputs"
class IOConfPwm(DBObject):
TABLENAME="ioconf_pwm"
class Analog(DBObject):
TABLENAME="analog"
......@@ -224,6 +236,8 @@ class StatsData(DBObject):
class StatsHistory(DBObject):
TABLENAME="stats_history"
def cleanFlags():
Registry.getConfig().delete("flags", where=["expire<="+str(time.time())])
......
......@@ -467,6 +467,41 @@ class domotikaService(service.Service):
self.upnp_detected_ips=[]
return dmdb.resetDynMediaSources()
def _syncBoards(self, res): # XXX Make which i/o/a is synced selectively
if res:
for b in res:
p=pluggableBoards.getBoardPlugin(b.type, ConvenienceCaller(lambda c: self._callback('board', c)))
if b:
pboard = p.getBoard(b.ip, b.webport, self.boardsyspwd, str(self.config.get('general', 'language')))
pboard.syncAnalogs()
pboard.syncInputs()
pboard.syncOutputs()
#pboard.syncPwm()
return True
def syncBoards(self, bid=False, *a, **kw):
if not bid:
return dmdb.DMBoards.find(where=['online=1']).addCallback(self._syncBoards)
return dmdb.DMBoards.find(where=['online=1 and id="%s"' % str(bid)]).addCallback(self._syncBoards)
def _pushBoards(self, res): # XXX Make which i/o/a is pushed selectively
if res:
for b in res:
p=pluggableBoards.getBoardPlugin(b.type, ConvenienceCaller(lambda c: self._callback('board', c)))
if b:
pboard = p.getBoard(b.ip, b.webport, self.boardsyspwd, str(self.config.get('general', 'language')))
pboard.pushAnalogs()
pboard.pushInputs()
pboard.pushOutputs()
#pboard.pushPwm()
return True
def pushBoards(self, bid=False, *a, **kw):
if not bid:
return dmdb.DMBoards.find(where=['online=1']).addCallback(self._pushBoards)
return dmdb.DMBoards.find(where=['online=1 and id="%s"' % str(bid)]).addCallback(self._pushBoards)
def autoDetectBoards(self, *a, **kw):
log.info("Start building boardlist")
......@@ -592,12 +627,15 @@ class domotikaService(service.Service):
dmdb.Analog.find(where=["""ananum=? AND board_name=? """, a.num, name ]).addCallback(self.insertAnalog,
a, name, fwver
)
bplugin.syncAnalogs()
if bplugin.hasInputs:
for i in bplugin.getInputsNames().values():
dmdb.Input.find(where=["""inpnum=? AND board_name=? """, i.num, name]).addCallback(self.insertInput,
i, name, fwver
)
bplugin.syncInputs()
if bplugin.hasOutputs:
for o in bplugin.getOutputsConfs().values():
# OUTPUT NOTE: is based on output not on relay! an output can have more than 1 relay...
......@@ -607,6 +645,7 @@ class domotikaService(service.Service):
dmdb.Output.find(where=["""outnum=? AND board_name=? """, i, name]).addCallback(self.insertOutput,
o, name, fwver
)
bplugin.syncOutputs()
def insertOutput(self, res, out, name, fwver):
......@@ -767,7 +806,7 @@ class domotikaService(service.Service):
def addBoard(self, btype, fwver, name, ip, webport=80, ptype='UDP4', port=6654):
log.debug(" ".join(["ADDBoard", str(name), str(btype), str(fwver), str(ip)]))
p=pluggableBoards.getBoardPlugin(btype)
p=pluggableBoards.getBoardPlugin(btype, ConvenienceCaller(lambda c: self._callback('board', c)))
if p:
pboard = p.getBoard(ip, webport, self.boardsyspwd, str(self.config.get('general', 'language')))
log.info("Support module for "+str(btype)+" board LOADED")
......@@ -911,6 +950,21 @@ class domotikaService(service.Service):
except:
pass
def ioConfig(what, act, who, **args):
what = what.lower()
act = act.lower()
if what=='analog':
if act=='setlimits':
maxval=False
minval=False
status='DEFAULT'
if 'max' in args.keys() and genutils.is_number(args['max']):
maxval=int(args['max'])
if 'min' in args.keys() and genutils.is_number(args['min']):
minval=int(args['min'])
if 'status' in args.keys():
status=args['status']
def executeAction(self, command):
def multipleInsertNotify(dbres, nsrc, expire, msg):
if dbres:
......@@ -924,6 +978,20 @@ class domotikaService(service.Service):
subprocess.Popen(
command.replace("\r\n", " "),
shell=True, preexec_fn = os.setsid)
elif command.startswith("IOCONF ") or command.startswith("IOCONF:"):
command=command[7:]
if ':' in command:
cl=command.split(':')
else:
cl=command.split()
if len(cl)>=3:
what=cl[0]
act=cl[1]
who=cl[2]
if len(cl)>3:
self.ioConfig(what, act, who, **dict([i.split('=') for i in cl[3:] if '=' in i and len(i.split('='))>1 and i.split('=')[1]]))
else:
self.ioConfig(what, act, who)
elif command.startswith("NETSTATUS ") or command.startswith("NETSTATUS:"):
command=command[10:]
nst=command.split()[0]
......@@ -2113,6 +2181,12 @@ class domotikaService(service.Service):
self.autoDetectBoards()
return self.daemonstatus
def web_on_startSync(self, bid=False):
return self.syncBoards(bid=bid)
def web_on_startPush(self, bid=False):
return self.pushBoards(bid=bid)
def web_on_getAuth(self, usr, pwd):
return dmdb.Users.find(where=["username='%s' AND passwd='%s' AND active=1" % ( usr, pwd)])
......@@ -2415,4 +2489,10 @@ class domotikaService(service.Service):
def fagi_on_voiceReceived(self, txt, confidence=0.0, lang="it"):
return self.voiceRecognized(txt,confidence,lang,voicesrc='VoIP')
def board_on_setOTP(self, pwd, ipdst):
log.info('SETOTP for '+str(ipdst)+' ('+str(pwd)+')')
self.sendCommand('SETOTP'+str(pwd), msgtype=C.IKAP_MSG_ACTION, ctx=C.IKAP_CTX_SYSTEM, act=C.IKAP_ACT_BOARD, ipdst=ipdst)
return defer.succeed(True)
def board_on_boardOK(self, bid):
self.clientSend('boardOK', bid)
......@@ -312,6 +312,24 @@ class BoardRest(RestCore):
self.core.startAutoDetection(True)
ResponseConversion(request, entity='OK')
@route("/syncall")
@wrapResponse
def boardForceAutodetect(self, request, *a, **kw):
self.core.startSync()
ResponseConversion(request, entity='OK')
@route("/syncboardbyid/<int:boardid>")
@wrapResponse
def syncBoardById(self, request, boardid):
self.core.startSync(boardid)
ResponseConversion(request, entity='OK')
@route("/pushboardbyid/<int:boardid>")
@wrapResponse
def pushBoardById(self, request, boardid):
self.core.startPush(boardid)
ResponseConversion(request, entity='OK')
class CronRest(RestCore):
......
#!/bin/bash
cd `dirname $0`
./boardcmd.py $1 BOOTLOAD 0.0.0.0 eth0
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment