Bonjour,
Du temps du plugin-blea, j’avais intégré ma brosse à dents dans celui-ci :
Résumé
from bluepy import btle
import time
import logging
import globals
import struct
from multiconnect import Connector
from notification import Notification
class OralB():
def __init__(self):
self.name = 'oralb'
self.ignoreRepeat = False
self.characteristicHandles = {
'battery': '0x002d'
}
def isvalid(self,name,manuf='',data='',mac=''):
if manuf.lower().startswith("dc00"):
return True
def parse(self,data,mac,name,manuf):
action={}
action['present'] = 1
logging.debug('OralB------ Parse => Manufacturer : ' + manuf )
status = manuf[10:12]
if status == '02':
logging.debug('OralB------ Advertising Data => Status : ' + str(status) + ' => Brushing stopped')
action['status'] = 0
elif status == '03':
logging.debug('OralB------ Advertising Data => Status : ' + str(status) + ' => Brushing in progress')
action['status'] = 1
pressure = int(manuf[12:14],16)
logging.debug('OralB------ Advertising Data => Pressure : ' + str(pressure))
action['pressure'] = pressure
brushingDurationMin = int(manuf[14:16],16)
brushingDurationSec = int(manuf[16:18],16)
brushingDuration = brushingDurationMin * 60 + brushingDurationSec
logging.debug('OralB------ Advertising Data => Brushing Duration : ' + str(brushingDuration) + ' seconde(s)')
action['brushingDuration'] = brushingDuration
if status == '02' and brushingDuration > 0:
logging.debug('OralB------ Advertising Data => Previous Brushing Duration : ' + str(brushingDuration) + ' seconde(s)')
action['previousBrushingDuration'] = brushingDuration
mode = manuf[18:20]
if mode == '01':
action['mode'] = 'Propreté'
logging.debug('OralB------ Advertising Data => Mode : ' + str(mode) + ' => Propreté')
elif mode =='02':
action['mode'] = 'Douceur'
logging.debug('OralB------ Advertising Data => Mode : ' + str(mode) + ' => Douceur')
elif mode =='03':
action['mode'] = 'Massage'
logging.debug('OralB------ Advertising Data => Mode : ' + str(mode) + ' => Massage')
elif mode =='04':
action['mode'] = 'Blanchiment'
logging.debug('OralB------ Advertising Data => Mode : ' + str(mode) + ' => Blanchiment')
elif mode =='05':
action['mode'] = 'Nettoyage Approfondi'
logging.debug('OralB------ Advertising Data => Mode : ' + str(mode) + ' => Nettoyage Approfondi')
quadrant = int(manuf[20:22],16)
logging.debug('OralB------ Advertising Data => Quadrant : ' + str(quadrant))
action['quadrant'] = quadrant
if status == '02' and brushingDuration == 0 and quadrant == 15:
try:
conn = Connector(mac)
conn.connect()
if not conn.isconnected:
conn.connect()
if not conn.isconnected:
return
battery = conn.readCharacteristic(self.characteristicHandles['battery'])
logging.debug('OralB------ Refreshing Data => Battery Hex : ' + str(battery.hex()) + ' / Dec :' + str(int(str(battery.hex()),16)) + ' %')
action['battery'] = int(str(battery.hex()),16)
action['id'] = mac
logging.debug('OralB------'+str(action))
except Exception as e:
logging.error(str(e))
return action
def read(self,mac):
result={}
try:
conn = Connector(mac)
conn.connect()
if not conn.isconnected:
conn.connect()
if not conn.isconnected:
return
battery = conn.readCharacteristic(self.characteristicHandles['battery'])
logging.debug('OralB------ Refreshing Data => Battery Hex : ' + str(battery.hex()) + ' / Dec :' + str(int(str(battery.hex()),16)) + ' %')
result['battery'] = int(str(battery.hex()),16)
result['id'] = mac
logging.debug('OralB------'+str(result))
return result
except Exception as e:
logging.error(str(e))
globals.COMPATIBILITY.append(OralB)
et j’utilisais le widget suivant grâce à Spine :
Le cadran avance en fonction de la durée qui est affichée au centre et passe en rouge si la pression est différente de 0.
Résumé
<div class="eqLogic-widget eqLogic allowResize" style="height: #height#;width: #width#;border:#border#;border-radius:#border-radius#;background-color: #background-color#;color: #color#;#style#" data-eqLogic_id="#id#" data-eqLogic_uid="#uid#" data-version="#version#">
<span class="cmd refresh pull-right cursor" data-cmd_id="#refresh_id#">
<i class="fas fa-sync"></i>
</span>
<center class="widget-name"><a href="#eqLink#">#name_display# <span class="object_name">#object_name#</span></a></center>
<center>
<div class="cmd cmd-widget #status_history#" data-type="info" data-subtype="binary" data-template="tmpliconline" data-cmd_id="#status_id#" data-cmd_uid="#status_uid#" data-version="#version#" data-eqLogic_id="#id#">
<div class="content-xs">
<span class="cmdName #status_hide_name#"><strong>#status_name_display# </strong></span> <span class="iconCmdLine"></span>
</div>
</div>
</center>
<center>
<div class="cmd cmd-widget #previousBrushingDuration_history#" data-type="info" data-subtype="numeric" data-template="line" data-cmd_id="#previousBrushingDuration_id#" data-cmd_uid="#previousBrushingDuration_uid#" data-version="#version#" data-eqLogic_id="#id#">
<div class="content-xs">
<span class="cmdName #previousBrushingDuration_hide_name#"><strong>#previousBrushingDuration_name_display# </strong></span> <strong class="state"></strong> #previousBrushingDuration_unite#
</div>
</div>
</center>
<center>
<div class="cmd cmd-widget #pressure_history#" data-type="info" data-subtype="numeric" data-template="line" data-cmd_id="#pressure_id#" data-cmd_uid="#pressure_uid#" data-version="#version#" data-eqLogic_id="#id#">
<div class="content-xs">
<span class="cmdName #pressure_hide_name#"><strong>#pressure_name_display# </strong></span> <strong class="state"></strong> #pressure_unite#
</div>
</div>
</center>
<center>
<div class="cmd cmd-widget #brushingDuration_history#" data-type="info" data-subtype="numeric" data-template="default" data-cmd_id="#brushingDuration_id#" data-cmd_uid="#brushingDuration_uid#" data-version="#version#" data-eqLogic_id="#id#" title="Date de valeur : #brushingDuration_valueDate#<br/>Date de collecte : #brushingDuration_collectDate#" >
<div class="content-sm">
<div class="gaugeBrushingDuration cursor #brushingDuration_history#" data-cmd_id="#brushingDuration_id#"></div>
</div>
</div>
</center>
<center>
<div class="cmd cmd-widget #mode_history#" data-type="info" data-subtype="string" data-template="default" data-cmd_id="#mode_id#" data-cmd_uid="#mode_uid#" data-version="#version#" data-eqLogic_id="#id#">
<div class="content-xs">
<span class="iconCmdLine"></span> <strong class="state"></strong>
</div>
</div>
</center>
<center>
<div class="cmd cmd-widget #battery_history#" data-type="info" data-subtype="numeric" data-template="line" data-cmd_id="#battery_id#" data-cmd_uid="#battery_uid#" data-version="#version#" data-eqLogic_id="#id#">
<div class="content-xs">
<i class="fas fa-battery-full"></i> <strong class="state"></strong> #battery_unite#
</div>
</div>
</center>
<style>
.gaugeBrushingDuration {
width: 120px;
height: 120px;
}
.gaugeBrushingDuration .highcharts-pane {
fill: var(--el-defaultColor);
}
body[data-theme="core2019_Dark"] .gaugeBrushingDuration .highcharts-tick {
stroke: rgb(38, 38, 38);
}
body[data-theme="core2019_Light"] .gaugeBrushingDuration .highcharts-tick {
stroke: rgb(249, 249, 250);
}
.gaugeBrushingDuration .highcharts-container .highcharts-axis-line {
stroke: transparent;
}
</style>
<script>
/*var brushingColor = '';
function changeColor(pressure){
if (pressure == 192){
brushingColor = 'red';
} else {
brushingColor = 'blue';
}
console.log("Change Color : " + pressure);
console.log("Change Color : " + brushingColor);
}
function getColor(){
console.log("Get Color : " + brushingColor);
return brushingColor;
}*/
if ('#refresh_id#' != ''){
$('.eqLogic[data-eqLogic_uid=#uid#] .refresh').on('click', function () {
jeedom.cmd.execute({id: '#refresh_id#'});
});
}else{
$('.eqLogic[data-eqLogic_uid=#uid#] .refresh').remove();
}
jeedom.cmd.update['#status_id#'] = function(_options) {
var cmd = $('.cmd[data-cmd_id=#status_id#]')
cmd.attr('title','Date de valeur : '+_options.valueDate+'<br/>Date de collecte : '+_options.collectDate)
if (_options.display_value == '0') {
$('.cmd[data-cmd_id=#status_id#] .iconCmdLine').empty().append('<i class="fas fa-times icon_red"></i>')
} else {
$('.cmd[data-cmd_id=#status_id#] .iconCmdLine').empty().append('<i class="fas fa-spin fa-spinner icon_green"></i>')
}
}
jeedom.cmd.update['#status_id#']({display_value:'#status#',valueDate:'#status_valueDate#',collectDate:'#status_collectDate#',alertLevel:'#status_alertLevel#'})
jeedom.cmd.update['#mode_id#'] = function(_options) {
var cmd = $('.cmd[data-cmd_id=#mode_id#]')
cmd.attr('title','Date de valeur : '+_options.valueDate+'<br/>Date de collecte : '+_options.collectDate)
if (_options.display_value == 'Propreté') {
$('.cmd[data-cmd_id=#mode_id#] .iconCmdLine').empty().append('<i class="fas fa-tooth icon_blue"></i>')
} else if (_options.display_value == 'Douceur') {
$('.cmd[data-cmd_id=#mode_id#] .iconCmdLine').empty().append('<i class="fas fa-feather-alt icon_blue"></i>')
} else if (_options.display_value == 'Massage') {
$('.cmd[data-cmd_id=#mode_id#] .iconCmdLine').empty().append('<i class="fas fa-tooth icon_blue"></i>')
} else if (_options.display_value == 'Blanchiment') {
$('.cmd[data-cmd_id=#mode_id#] .iconCmdLine').empty().append('<i class="far fa-gem icon_blue"></i>')
} else if (_options.display_value == 'Nettoyage Approfondi') {
$('.cmd[data-cmd_id=#mode_id#] .iconCmdLine').empty().append('<i class="fas fa-tooth icon_blue"></i>')
}
cmd.find('.state').empty().append(_options.display_value)
}
jeedom.cmd.update['#mode_id#']({display_value:'#mode#',valueDate:'#mode_valueDate#',collectDate:'#mode_collectDate#',alertLevel:'#mode_alertLevel#'})
jeedom.cmd.update['#previousBrushingDuration_id#'] = function(_options) {
var cmd = $('.cmd[data-cmd_id=#previousBrushingDuration_id#]')
cmd.attr('title','Date de valeur : '+_options.valueDate+'<br/>Date de collecte : '+_options.collectDate)
cmd.find('.state').empty().append(_options.display_value);
}
jeedom.cmd.update['#previousBrushingDuration_id#']({display_value:'#previousBrushingDuration#',valueDate:'#previousBrushingDuration_valueDate#',collectDate:'#previousBrushingDuration_collectDate#',alertLevel:'#previousBrushingDuration_alertLevel#'})
jeedom.cmd.update['#pressure_id#'] = function(_options) {
var cmd = $('.cmd[data-cmd_id=#pressure_id#]')
cmd.attr('title','Date de valeur : '+_options.valueDate+'<br/>Date de collecte : '+_options.collectDate)
cmd.find('.state').empty().append(_options.display_value);
/*changeColor(_options.display_value);*/
}
jeedom.cmd.update['#pressure_id#']({display_value:'#pressure#',valueDate:'#pressure_valueDate#',collectDate:'#pressure_collectDate#',alertLevel:'#pressure_alertLevel#'})
jeedom.cmd.update['#battery_id#'] = function(_options) {
var cmd = $('.cmd[data-cmd_id=#battery_id#]')
cmd.attr('title','Date de valeur : '+_options.valueDate+'<br/>Date de collecte : '+_options.collectDate)
cmd.find('.state').empty().append(_options.display_value);
}
jeedom.cmd.update['#battery_id#']({display_value:'#battery#',valueDate:'#battery_valueDate#',collectDate:'#battery_collectDate#',alertLevel:'#battery_alertLevel#'})
jeedom.cmd.update['#brushingDuration_id#'] = function(_options) {
$('.cmd[data-cmd_id=#brushingDuration_id#]').attr('title','Date de valeur : '+_options.valueDate+'<br/>Date de collecte : '+_options.collectDate)
/*$('.cmd[data-cmd_uid=#brushingDuration_uid#] .gaugeBrushingDuration').highcharts().setOptions({colors: ['red']})*/
$('.cmd[data-cmd_uid=#brushingDuration_uid#] .gaugeBrushingDuration').highcharts().series[0].points[0].update(_options.display_value)
}
if (is_numeric('#brushingDuration#')) {
/*brushingColor = getColor();*/
$('.cmd[data-cmd_uid=#brushingDuration_uid#] .gaugeBrushingDuration').empty().highcharts({
chart: {
style: {
fontFamily: 'Roboto'
},
type: 'solidgauge',
plotBackgroundColor: null,
plotBackgroundImage: null,
backgroundColor: null,
plotBorderWidth: 0,
plotShadow: false,
height: 106,
spacingTop: 0,
spacingLeft: 0,
spacingRight: 0,
spacingBottom: 0,
borderWidth : 0
},
title: null,
pane: {
center: ['50%', '50%'],
size: 100,
startAngle: 0,
endAngle: 360,
background: {
innerRadius: '70%',
outerRadius: '100%',
shape: 'arc',
borderWidth: 0,
}
},
tooltip: {
enabled: false
},
// the value axis
yAxis: {
lineWidth: 0,
minorTickInterval: null,
tickInterval: 30,
tickWidth: 4,
tickLength: 15,
tickPosition: 'inside',
labels : {enabled: false},
lineWidth: 0,
min: 0,
max: 120,
zIndex: 6,
title: {
text: ''
}
},
labels : {enabled: false},
plotOptions: {
solidgauge: {
dataLabels: {
y: 9,
borderWidth: 0,
useHTML: true
},
rounded: true
}
},
credits: {
enabled: false
},
exporting : {
enabled: false
},
series: [
{
name: '',
data: [{
y: Math.round(parseFloat('#brushingDuration#') * 10) / 10,
/* color: '#pressure#' == 192 ? "red" : "blue"}],*/
color: '#brushingColor#'}],
radius: '100%',
innerRadius: '70%',
dataLabels: {
y: 6,
format: '<span style="color: var(--link-color); position: relative; top: -28px; font-size: 24px">{y}</span>'
},
}
]
})
} else {
$('.cmd[data-cmd_uid=#brushingDuration_uid#] .gaugeBrushingDuration').append('<center><span class="label label-danger">#brushingDuration#</span></center>')
}
</script>
</div>
Je voudrais maintenant l’utiliser sur un équipement en dehors du plugin-blea mais les widgets n’étant pas ma tasse de thé, s’il y avait une âme charitable pour m’aider à le modifier, je suis preneur.
Merci.