get weight from GATT characteristics value in react-native-ble-plx - android

I am developing an react-native app that gets the weight value of a scale(MI SCALE2) that supports Bluetooth.(I have no knowledge of bluetooth.)
// version
"react-native": "0.66.1",
"react-native-ble-plx": "https://github.com/below/react-native-ble-plx",
I was able to get these values ​​when I got on the scale.
# feature
{"data": [33, 0, 0, 0], "type": "Buffer"}
# Weight
{"data": [2, 156, 74, 178, 7, 1, 7, 22, 33, 1], "type": "Buffer"}
{"data": [2, 156, 74, 178, 7, 1, 7, 22, 33, 1], "type": "Buffer"}
{"data": [2, 156, 74, 178, 7, 1, 7, 22, 33, 1], "type": "Buffer"}
{"data": [2, 156, 74, 178, 7, 1, 7, 22, 33, 2], "type": "Buffer"}
{"data": [2, 156, 74, 178, 7, 1, 7, 22, 33, 2], "type": "Buffer"}
{"data": [34, 156, 74, 178, 7, 1, 7, 22, 33, 2], "type": "Buffer"}
{"data": [162, 156, 74, 178, 7, 1, 7, 22, 33, 6], "type": "Buffer"}
After reading the Q&A in several places, I know that it is necessary to combine the value of the feature with the value of the weight array.
I want to know how to get the weight value from my result like "94.9kg, 95.5kg, ..."
Below is the code I wrote.
manager.startDeviceScan(null, null, (error, device) => {
if (error) {
console.log('error : ' + error);
return;
}
console.log(device.name);
if (device.name === 'MI SCALE2') {
console.log('detected!!');
manager.stopDeviceScan();
device
.connect()
.then(device => {
return device.discoverAllServicesAndCharacteristics();
})
.then(device => {
return device.services();
})
.then(services => {
const result = services.filter(id => id.uuid.indexOf('181d') != -1); // 181d is Weight Scale -> org.bluetooth.service.weight_scale;
return result[0].characteristics();
})
.then(characters => {
const resultDateObject = characters.filter(
data => data.uuid.indexOf('2a2b') != -1, // 2a2b is Current Time -> org.bluetooth.characteristic.current_time;
);
const resultWeightFeature = characters.filter(
data => data.uuid.indexOf('2a9e') != -1, // 2a9e is Weight Scale Feature -> org.bluetooth.characteristic.weight_scale_feature
);
const resultWeight = characters.filter(
data => data.uuid.indexOf('2a9d') != -1, // 2a9d is Weight Measurement -> org.bluetooth.characteristic.weight_measurement;
);
const resultPosition2D = characters.filter(
data => data.uuid.indexOf('2a2f') != -1, // 2a2f is Position 2D -> org.bluetooth.characteristic.position_2d;
);
// const DeviceID = resultWeightFeature[0].deviceID;
// const ServiceUUID = resultWeightFeature[0].serviceUUID;
// const DateCharacterUUID = resultDateObject[0].uuid;
// const WeightFeatureCharacterUUID = resultWeightFeature[0].uuid;
// const WeightCharacterUUID = resultWeight[0].uuid;
// const PositionCharacterUUID = resultPosition2D[0].uuid;
resultWeight[0].monitor((error, characteristic) => {
if (error) {
console.log('error:::::', error);
return;
}
let your_bytes = Buffer.from(characteristic.value, "base64");
console.log(your_bytes);
})
return resultWeightFeature[0].read();
}).then(feature => {
let feature_bytes = Buffer.from(feature.value, "base64");
console.log('feature.value');
console.log(feature_bytes);
})
}
});

As far as I understand your Code, your weight scale makes use of Bluetooth Weight Scale Profile and Weight Scale Service.
The data you find in the corresponding characteristics needs to be interpreted as described in Personal Health Devices Transcoding
Edit:
You can find more information on the data structure here:
GATT Specification Supplement 5
example:
Feature([33,0,0,0]) => 0x00000011 => ...00 0010 0001 =>
value
description
1
Time Stamp Supported: True
0
Multiple Users Supported: False
0
BMI Supported: False
0100
Weight Measurement Resolution: Resolution of 0.05 kg or 0.1 lb
000
Height Measurement Resolution: Not specified
Weight = [34, 156, 74, 178, 7, 1, 7, 22, 33, 2]
=> 0x22 0x9c 0x4a 0xb2 0x07 0x01 0x07 0x16 0x21 0x02
First byte is a flags field => 0x22 => 0010 0010
value
description
0
Measurement Units: SI
1
Time Stamp present: True
0
User ID present: False
0
BMI and Height present: False
0010
Reserved for Future Use
Weight in kilograms with resolution 0.005 (uint16) => 0x4a9c => 95,5 kg
Time Stamp 0xb2 0x07 0x01 0x07 0x16 0x21 0x02
year(uint16) => 0x07b2 => 1970
month(uint8) => 0x01 => 1
day(uint8) => 0x07 => 7
hours(uint8) => 0x16 => 22
minutes(uint8) => 0x21 => 33
seconds(uint8) => 0x02 => 2
date 1970-01-07T22:33:02

Related

How to add an onclick event on clusters? - Flutter MapBox

I've been trying pretty hard to add an onClick function on my clusters that zooms a bit on the map, but I can't figure out how to do so, and I can't find any help on the documentation.
I've been trying to work with controller.onCircleTappedand controller.onFeatureTapped but I don't understand how it's working, or how to link the callback to a particular cluster.
Thank you all!
Here's my current code:
`
Future<void> addGeojsonCluster() async {
var geojson = {
"type": "FeatureCollection",
"crs": { "type": "name", "properties": { "name": "pois" } },
"features": [
for(var marker in markers){
"type" : "Feature", "properties" : {"id" : marker.title}, "geometry": {"type" : "Point", "coordinates" : [marker.longitude, marker.latitude] }
},
]
};
await controller.addSource(
"poi",
GeojsonSourceProperties(
data: geojson,
cluster: true,
clusterMaxZoom: 14, // Max zoom to cluster points on
clusterRadius:
50, // Radius of each cluster when clustering points (defaults to 50)
)
);
await controller.addLayer(
"poi",
"poi-circles",
const CircleLayerProperties(
circleColor: [
Expressions.step,
[Expressions.get, 'point_count'],
'#51bbd6', //blue
100,
'#f1f075', //yellow
750,
'#f28cb1' //pink
],
circleRadius: [
Expressions.step,
[Expressions.get, 'point_count'],
20,
100,
30,
750,
40
]),
);
await controller.addSymbolLayer(
"poi",
"unclustered-point",
const SymbolLayerProperties(
textField: [Expressions.get, "id"],
textHaloWidth: 1,
textSize: 12.5,
textHaloColor: '#ffffff',
textOffset: [
Expressions.literal,
[0, 2]
],
iconImage: "images/mapbox_circle_marker.png",
iconSize: 2,
iconAllowOverlap: true,
textAllowOverlap: true,
textColor: '#000000',
textHaloBlur: 1,
),
filter: [
'!',
['has', 'point_count']
],
enableInteraction: true,
);
await controller.addLayer(
"poi",
"poi-count",
const SymbolLayerProperties(
textField: [Expressions.get, 'point_count_abbreviated'],
textFont: ['DIN Offc Pro Medium', 'Arial Unicode MS Bold'],
textSize: 12,
));
}
`
You need to register a OnTapListener on the whole map and query all the features on the map.
MapWidget(
onTapListener: _clickMap,
)
And in _clickMap you query for everything displayed on the map and decide depending on the return what to do. Here I zoom in to the next cluster step. Keep in mind, that there is currently a confirmed bug in the sdk. OnTapListener is not return ScreenCoordinates but geographical coordinates. So you need to convert them first with pixelForCoordinate.
void _clickMap(ScreenCoordinate coordinate) async {
ScreenCoordinate coordin = await mapboxMap!.pixelForCoordinate({
"coordinates": [coordinate.y, coordinate.x]
});
List<QueriedFeature?> features = await mapboxMap!.queryRenderedFeatures(
RenderedQueryGeometry(
type: Type.SCREEN_COORDINATE, value: json.encode(coordin.encode())),
RenderedQueryOptions(
layerIds: ['clusters', "unclustered-point"], filter: null));
if (features.isNotEmpty) {
if ((features[0]!.feature["properties"] as Map)['cluster'] != null) {
FeatureExtensionValue cluster = await mapboxMap!
.getGeoJsonClusterExpansionZoom(
'earthquakes', features[0]!.feature);
mapboxMap?.easeTo(
CameraOptions(
center: Point(
coordinates: Position(
(features[0]!.feature['geometry'] as Map)["coordinates"][0],
(features[0]!.feature['geometry'] as Map)["coordinates"][1],
)).toJson(),
zoom: double.parse(cluster.value!),
bearing: 0,
pitch: 0),
MapAnimationOptions(duration: 500, startDelay: 0));
}}}
Hope that helps :)

How i get by NFC-Scanning with Flutter/Android the same Uid like when i scanning with iOS?

When i scan with my iOS app a NFC-Tag i get this result:
04ea1b72835c80
i think this is the Uid.
Now i program with Flutter and the NFC-Manager package a NFC-Reader for Android.
Now when i scan the same NFC Tag i get this Information:
{nfca: {identifier: [4, 234, 27, 114, 131, 92, 128], atqa: [68, 0], maxTransceiveLength: 253, sak: 0, timeout: 618}, mifareultralight: {identifier: [4, 234, 27, 114, 131, 92, 128], maxTransceiveLength: 253, timeout: 618, type: 2}, ndef: {identifier: [4, 234, 27, 114, 131, 92, 128], isWritable: true, maxSize: 492, canMakeReadOnly: true, cachedMessage: null, type: org.nfcforum.ndef.type2}}
i use this code in flutter:
void _tagRead() {
NfcManager.instance.startSession(onDiscovered: (NfcTag tag) async {
var mytag = tag.data;
result.value = tag.data ;
NfcManager.instance.stopSession();
});
}
i tried to parse the identifier in different ways but i didn´t get the same result how from iOS.
Anyone know the right way?
This
void _tagRead() {
NfcManager.instance.startSession(onDiscovered: (NfcTag tag) async {
var mytag = tag.data;
result.value = tag.data ;
NfcManager.instance.stopSession();
});
}
change to
void _tagRead() {
NfcManager.instance.startSession(onDiscovered: (NfcTag tag) async {
var mytag = tag.data["mifareultralight"]["identifier"].map((e) => e.toRadixString(16).padLeft(2, '0')).join(''); ;
result.value = mytag ;
NfcManager.instance.stopSession();
});
}
and i got 04ea1b72835c80

Node js equivalent code for android AES encryption

I am trying to encrypt my message in android and decrypt in node js server.
Android Code :
SecretKeySpec secretkeyspec = new SecretKeySpec("password".getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, secretkeyspec);
byte[] encoded = cipher.doFinal(s.getBytes());
System.out.println(Arrays.toString(encoded));
Node JS Code :
var crypto = require('crypto');
var CIPHER_ALGORITHM = 'aes-128-cbc';
var key = 'password';
var ivBuffer = new Buffer(16);
ivBuffer.fill(0);
var cipher = crypto.createCipheriv(CIPHER_ALGORITHM, new Buffer(key, 'utf-8'), ivBuffer);
var encryptedBuffer = cipher.update(plainText, 'utf-8');
var fBuf = new Int8Array(Buffer.concat([encryptedBuffer, cipher.final()]));
console.log(fBuf);
When i try to print the buffers im getting different values between android and node js.
Node Buffer :
[26,
116,
2,
-56,
-70,
121,
-44,
66,
101,
84,
-46,
127,
-70,
-42,
67,
31,
124,
-104,
-24,
88,
74,
4,
-22,
-70,
-39,
48,
-120,
-21,
37,
-15,
-24,
-30 ]
Android Buffer :
[26, 116, 2, -56, -70, 121, -44, 66, 101, 84, -46, 127, -70, -42, 67, 31, -92, 97, 16, -101, -45, -68, 108, 89, -125, 17, -71, 53, 2, -13, 31, -79]
could someone tell whats the android default AES equivalent node js decryption code.
I finally found the answer.
var cipher = crypto.createCipheriv(CIPHER_ALGORITHM, new Buffer(key, 'utf-8'), '');
var encryptedBuffer = cipher.update(plainText, 'utf-8');
var finalEncryptedBuffer = new Int8Array(Buffer.concat([encryptedBuffer, cipher.final()]));
console.log(encodeBytes(finalEncryptedBuffer));
Make sure mode of operation (for example, CBC) and padding (for example, PKCS5) are match between both implementations.

Jquery.flot - Android 4.2.2 WebKit 534.30 creates a second graph on the page

I have a jquery flot with filtering buttons below the graphic , which enable user to show the values on a weekly manner, or daily manner and so on.
The problem happens when the user clicks a filtering button, suddenly another flot chart above the first chart is created and it stays there till I leave the page and come back to the page.
I have the following code to show a graph as soon as user gets to the page ;
And the filtering button calls a function that has the same piece of code but with a different tick size (with week for example).
PS: I'm using Phonegap that prepares the app for the normal Android webview. The engine used depends on the Android version.
WebKit versions; Ref
Android 4.2.2 534.30 ( Another flot chart is created)
Android 4.4.x 537.36 ( Works as expected )
Code:
var plot = $.plot("#placeholder", [{
data: dAlle
}], {
series: {
lines: {
show: true
},
points: {
show: true
}
},
grid: {
hoverable: true,
clickable: true,
markings: [{
yaxis: {
from: 0,
to: 12
},
color: "#F2CDEA"
}, {
yaxis: {
from: rangeMin,
to: rangeMax
},
color: "#D7EEE1"
}]
},
xaxis: {
mode: "time",
minTickSize: [1, "month"],
/*min: theVeryFirstPoint,
max: theVeryLastPoint*/
},
yaxis: {
min: 0,
max: 12
}
});
The weird thing is that same logic works for Android with LG G2 API level 19 (4.4.2), but when I install the app into Samsung S2 with API Level 16 (4.2.2) , this problem occurs. Is there any way of preventing it from occuring?
CSS + JS imports are as follows ;
<link rel="stylesheet" href="css/jquery.mobile-1.4.2.min.css">
<link rel="stylesheet" type="text/css" href="css/main.css" />
<link rel="stylesheet" href="css/jqm-icon-pack-fa.css" />
<script type="text/javascript" src="cordova.js"></script>
<script src="js/jquery-1.11.2.min.js"></script>
<script src="js/jquery.mobile-1.4.5.min.js"></script>
<link href="css/examples.css" rel="stylesheet" type="text/css">
<script language="javascript" type="text/javascript" src="js/flot/jquery.flot.js"></script>
<script language="javascript" type="text/javascript" src="js/flot/jquery.flot.threshold.js"></script>
<script language="javascript" type="text/javascript" src="js/flot/jquery.flot.time.js"></script>
<script language="javascript" type="text/javascript" src="js/flot/jquery.flot.areamarkings.js"></script>
Filter function that is called ;
$("#a-uke").click(function() {
console.log("a dag filtering will be applied...");
var newDataSer = window.localStorage.getItem("storedData");
if (newDataSer != null) {
newDataSer = JSON.parse(newDataSer);
// Just convert into a new array object for the FIRST time
//if (dagButtonClicked == false) {
$.each(newDataSer, function(index, datapoint) {
datapoint[2] = datapoint[0];
datapoint[0] = (new Date(datapoint[0])).getHours();
console.log("hours created : " + datapoint[0]);
dagButtonClicked = true;
});
//}
if (newDataSer != null && newDataSer.length > 0) {
newDataSer.sort(function(x, y) {
console.log("sorting..");
return x[0] - y[0];
})
}
} else
newDataSer = [];
$.plot("#placeholder", [newDataSer], {
series: {
lines: {
show: true
},
points: {
show: true
}
},
grid: {
hoverable: true,
clickable: true,
areaMarkings: [{
points: [
[7, 12],
[24, 12],
[24, 0],
[7, 0]
],
lineWidth: 0,
fillColor: "#F2CDEA"
}, {
points: [
[7, rangeBr1],
[7, rangeBr2],
[10, rangeBr2],
[10, rangeBr1]
], // Green for breakfast
lineWidth: 0,
fillColor: "#D7EEE1"
}, {
points: [
[7, rangeBr2],
[7, rangeBr3],
[10, rangeBr3],
[10, rangeBr2]
], // Gradient1 Top for breakfast
lineWidth: 0,
fillColor: "#DFE4E3"
}, {
points: [
[7, rangeBr3],
[7, rangeBr4],
[10, rangeBr4],
[10, rangeBr3]
], // Gradient2 Top for breakfast
lineWidth: 0,
fillColor: "#E7DAE6"
}, {
points: [
[7, rangeBrBot2],
[7, rangeBrBot3],
[10, rangeBrBot3],
[10, rangeBrBot2]
], // Gradient1 Bottom for breakfast
lineWidth: 0,
fillColor: "#DFE4E3"
}, {
points: [
[7, rangeBrBot1],
[7, rangeBrBot2],
[10, rangeBrBot2],
[10, rangeBrBot1]
], // Gradient2 Bottom for breakfast
lineWidth: 0,
fillColor: "#E7DAE6"
}, {
points: [
[10, rangeMin],
[10, rangeMaxGrad],
[24, rangeMaxGrad],
[24, rangeMin]
], // Green for the rest
lineWidth: 0,
fillColor: "#D7EEE1"
}, {
points: [
[10, rangeMaxGrad],
[10, rangeMaxGrad2],
[24, rangeMaxGrad2],
[24, rangeMaxGrad]
], // Gradient1 top for the rest
lineWidth: 0,
fillColor: "#DFE4E3"
}, {
points: [
[10, rangeMaxGrad2],
[10, rangeMaxGrad3],
[24, rangeMaxGrad3],
[24, rangeMaxGrad2]
], // Gradient2 top for the rest
lineWidth: 0,
fillColor: "#E7DAE6"
}, {
points: [
[10, rangeMinGrad2],
[10, rangeMin],
[24, rangeMin],
[24, rangeMinGrad2]
], // Gradient1 bottom for the rest
lineWidth: 0,
fillColor: "#DFE4E3"
}, {
points: [
[10, rangeMinGrad3],
[10, rangeMinGrad2],
[24, rangeMinGrad2],
[24, rangeMinGrad3]
], // Gradient2 bottom for the rest
lineWidth: 0,
fillColor: "#E7DAE6"
}]
},
xaxis: {
tickFormatter: getAmPmHour,
min: 7,
max: 24
},
yaxis: {
min: 0,
max: 12
}
});
});
Not sure what is causing that bug, but there are two possible solutions you can try:
1) You can clear the old plot before creating the new one:
$('#placeholder').empty();
$.plot("#placeholder", [newDataSer], { /* your new options */ });
2) You can use the existing plot instead of creating a new one (which is the recommended way):
plot.setData([newDataSer]);
plot.getOptions().grid.areaMarkings = [ /* your new markings / options */ ];
plot.getOptions().xaxis = { /* your new options */ };
plot.setupGrid();
plot.draw();

Zooming in highchart makes line disappear

I'm using highchart in an android app to display a dynamic chart that is updated every 3 secs and displayed over one day.
My chart is composed of two fixed data series displaying the limit that the monitored data should not exceed, and obviously the monitored data (power value)
All the power value from 00:05 to the moment the chart is loaded, are first displayed. And then, every 3 seconds, a value is added to this serie.
The problem is when I try to zoom to the end point of my power values. The power data line (and only this one) disappear when I zoom in. If I zoom out, the line reappears. But if I zoom on an area where the end point of my data power line is not displayed, everything goes right.
I tried to remove the two fixed serie (it adjust my chart height to the length of the power data line but whatever), and the same zoom problem appears. I can't zoom to the end point of my power data line but I can zoom anywhere else.
I also tried to use datagrouping, but the problem stay the same
Here is my code:
$(function() {
$(document).ready(function() {
Highcharts.setOptions({
global: {
useUTC: true
}
});
var dataPower = Android.getDayHistory((new Date()).getHours(), (new Date()).getMinutes(), (new Date()).getSeconds());
//var dataPower = [];
console.log(dataPower);
// Create the chart
$('#container').highcharts(
'StockChart',
{
chart : {
type : 'line',
backgroundColor : '#d6d7d4',
ignoreHiddenSeries: false,
zoomType : 'x',
marginRight : 10,
events : {
load : function() {
// set up the updating of the chart each second
var series = this.series[0];
setInterval(function() {
var x = (new Date()).getTime(), // current time
y = Android.getData((new Date()).getHours(),(new Date()).getMinutes(), (new Date()).getSeconds());
series.addPoint([ x, y ]);
Android.checkAlert((new Date()).getHours(),(new Date()).getMinutes(), (new Date()).getSeconds());
}, 3000);
}
},
},
rangeSelector : {
buttons : [ {
type : 'minute',
count : 2,
text : '2m'
}, {
type : 'minute',
count : 5,
text : '5m'
}, {
type : 'minute',
count : 30,
text : '30m'
}, {
type : 'hour',
count : 1,
text : '1h'
}, {
type : 'all',
text : 'All'
} ],
selected : 4,
inputEnabled : false,
},
xAxis : {
ordinal : false,
minRange : 36000
},
yAxis : {
title : {
text : 'Power (MW)'
},
max : 500,
plotBands : [ {
from : 0,
to : 100,
color : 'rgba(247, 247, 247, 0.3)'
}, {
from : 100,
to : 200,
color : 'rgba(215, 216, 212, 0.3)'
}, { // Light breeze
from : 200,
to : 300,
color : 'rgba(247, 247, 247, 0.3)'
}, { // Light breeze
from : 300,
to : 400,
color : 'rgba(215, 216, 212, 0.3)'
}, {
from : 400,
to : 500,
color : 'rgba(247, 247, 247, 0.3)'
} ]
},
plotOptions: {
spline: {
lineWidth: 2,
states: {
hover: {
enabled: true,
lineWidth: 3
}
},
marker: {
enabled: false,
states: {
hover: {
enabled : true,
radius: 5,
lineWidth: 1
}
}
}
}
},
title : {},
subtitle : {},
navigator : {
enabled : false
},
scrollbar : {
enabled : false
},
credits : {
enabled : false
},
series : [
{
name : 'Power',
data : eval('[' + dataPower + ']'),
pointStart : Date.UTC((new Date()).getFullYear(),
(new Date()).getMonth(), (new Date()).getDate()),
pointInterval : 3000,
},
{
data : [
[
Date.UTC(
(new Date()).getFullYear(),
(new Date()).getMonth(),
(new Date()).getDate(), 0,
5, 0), 40 ],
[
Date.UTC(
(new Date()).getFullYear(),
(new Date()).getMonth(),
(new Date()).getDate(), 7,
0, 0), 40 ],
[
Date.UTC(
(new Date()).getFullYear(),
(new Date()).getMonth(),
(new Date()).getDate(), 7,
30, 0), 440 ],
[
Date.UTC(
(new Date()).getFullYear(),
(new Date()).getMonth(),
(new Date()).getDate(), 11,
57, 0), 440 ],
[
Date.UTC(
(new Date()).getFullYear(),
(new Date()).getMonth(),
(new Date()).getDate(), 12,
3, 0), 390 ],
[
Date.UTC(
(new Date()).getFullYear(),
(new Date()).getMonth(),
(new Date()).getDate(), 13,
57, 0), 390 ]
,
[
Date.UTC(
(new Date()).getFullYear(),
(new Date()).getMonth(),
(new Date()).getDate(), 14,
3, 0), 440 ],
[
Date.UTC(
(new Date()).getFullYear(),
(new Date()).getMonth(),
(new Date()).getDate(), 17,
3, 0), 440 ],
[
Date.UTC(
(new Date()).getFullYear(),
(new Date()).getMonth(),
(new Date()).getDate(), 23,
55, 0), 40 ]
],
type : 'line',
color : "#d3a6ad",
enableMouseTracking : false
},
{
data : [
[
Date.UTC(
(new Date()).getFullYear(),
(new Date()).getMonth(),
(new Date()).getDate(), 0,
5, 0), 60 ],
[
Date.UTC(
(new Date()).getFullYear(),
(new Date()).getMonth(),
(new Date()).getDate(), 7,
0, 0), 60 ],
[
Date.UTC(
(new Date()).getFullYear(),
(new Date()).getMonth(),
(new Date()).getDate(), 7,
30, 0), 460 ],
[
Date.UTC(
(new Date()).getFullYear(),
(new Date()).getMonth(),
(new Date()).getDate(), 11,
57, 0), 460 ],
[
Date.UTC(
(new Date()).getFullYear(),
(new Date()).getMonth(),
(new Date()).getDate(), 12,
3, 0), 410 ],
[
Date.UTC(
(new Date()).getFullYear(),
(new Date()).getMonth(),
(new Date()).getDate(), 13,
57, 0), 410 ]
,
[
Date.UTC(
(new Date()).getFullYear(),
(new Date()).getMonth(),
(new Date()).getDate(), 14,
3, 0), 460 ],
[
Date.UTC(
(new Date()).getFullYear(),
(new Date()).getMonth(),
(new Date()).getDate(), 17,
3, 0), 460 ],
[
Date.UTC(
(new Date()).getFullYear(),
(new Date()).getMonth(),
(new Date()).getDate(), 23,
55, 0), 60 ]
],
type : 'line',
color : "#d3a6ad",
enableMouseTracking : false
} ]
});
});
});

Categories

Resources