Last active
August 29, 2015 14:09
-
-
Save lbrenman/8eea975abddee8fdb62d to your computer and use it in GitHub Desktop.
Appcelerator Titanium Alloy Bluetooth LE Weather Station using TI CC2541 SmartTag and Logical Labs BT LE Module
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// The contents of this file will be executed before any of | |
// your view controllers are ever executed, including the index. | |
// You have access to all functionality on the `Alloy` namespace. | |
// | |
// This is a great place to do any initialization for your app | |
// or create any global variables/functions that you'd like to | |
// make available throughout your app. You can easily make things | |
// accessible globally by attaching them to the `Alloy.Globals` | |
// object. For example: | |
// | |
// Alloy.Globals.someGlobalFunction = function(){}; | |
Alloy.Globals.audioOn=false; | |
Alloy.Globals.farenheitOn=false; | |
Alloy.Globals.firstRun=true; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
".container": { | |
backgroundColor:"white", | |
fullscreen: true, | |
navBarHidden: true | |
} | |
".colorLineVw": { | |
height: 1, | |
bottom: 0, | |
backgroundColor: "#f44d4a" | |
} | |
"#activityIndicatorVw": { | |
backgroundColor: "#D0000000", | |
borderRadius: 8, | |
borderWidth: 2, | |
borderColor: "gray", | |
height:60, | |
width:200 | |
} | |
"#activityIndicator": { | |
style: Ti.UI.ActivityIndicatorStyle.DARK, | |
color: "white", | |
indicatorColor: "white", | |
height:Ti.UI.SIZE, | |
width:Ti.UI.SIZE | |
} | |
"#activityIndicator[platform=ios]": { | |
style: Ti.UI.iPhone.ActivityIndicatorStyle.BIG_DARK | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var BluetoothLE = require('com.logicallabs.bluetoothle'); | |
var connectedPeripheral; | |
var BTReady = false; | |
// var index=0; | |
var BarometricPressureCalibrationValue; | |
var scanRunning = false; | |
var scanStatus, peripheralStatus, peripheralName; | |
var centralErrorCallback, centralOffCallback, | |
centralOnCallback; | |
var centralStateChangeCallbackAdded; | |
var callback; | |
var | |
BASE_UUID = '00000000-0000-1000-8000-00805F9B34FB'; | |
KEY_SERVICE_UUID = "0000ffe0-0000-1000-8000-00805f9b34fb", | |
KEY_DATA_UUID = "0000ffe1-0000-1000-8000-00805f9b34fb", | |
IR_TEMP_SERVICE_UUID = 'F000AA00-0451-4000-B000-000000000000', | |
IR_TEMP_DATA_CHAR_UUID = 'F000AA01-0451-4000-B000-000000000000', | |
IR_TEMP_CONFIG_CHAR_UUID = 'F000AA02-0451-4000-B000-000000000000', | |
HUMIDITY_SERVICE_UUID = 'F000AA20-0451-4000-B000-000000000000', | |
HUMIDITY_DATA_CHAR_UUID = 'F000AA21-0451-4000-B000-000000000000', | |
HUMIDITY_CONFIG_CHAR_UUID = 'F000AA22-0451-4000-B000-000000000000', | |
BARPRESSURE_SERVICE_UUID = 'F000AA40-0451-4000-B000-000000000000', | |
BARPRESSURE_DATA_CHAR_UUID = 'F000AA41-0451-4000-B000-000000000000', | |
BARPRESSURE_CONFIG_CHAR_UUID = 'F000AA42-0451-4000-B000-000000000000'; | |
BARPRESSURE_CALIBRATION_CHAR_UUID = 'F000AA43-0451-4000-B000-000000000000'; | |
function twosComp(value, bitCount) { | |
Ti.API.debug("cc2541_btle: twosComp()"); | |
if (value < Math.pow(2, bitCount - 1)) { | |
return value; | |
} | |
return value - Math.pow(2, bitCount); | |
} | |
function buildCalibrationInt(loByte, hiByte) { | |
Ti.API.debug("cc2541_btle: buildCalibrationInt()"); | |
return ((((hiByte) & 0x00FF) << 8)) + ((loByte) & 0x00FF); | |
} | |
function getBarPressureValue(buffer, calibrationVal) { | |
Ti.API.debug("cc2541_btle: getBarPressureValue()"); | |
var c1 = buildCalibrationInt(calibrationVal[0], calibrationVal[1]); | |
var c2 = buildCalibrationInt(calibrationVal[2], calibrationVal[3]); | |
var c3 = buildCalibrationInt(calibrationVal[4], calibrationVal[5]); | |
var c4 = buildCalibrationInt(calibrationVal[6], calibrationVal[7]); | |
var c5 = twosComp(buildCalibrationInt(calibrationVal[8], calibrationVal[9]),16); | |
var c6 = twosComp(buildCalibrationInt(calibrationVal[10], calibrationVal[11]),16); | |
var c7 = twosComp(buildCalibrationInt(calibrationVal[12], calibrationVal[13]),16); | |
var c8 = twosComp(buildCalibrationInt(calibrationVal[14], calibrationVal[15]),16); | |
Ti.API.debug("cc2541_btle: getBarPressureValue(), c1 = "+c1); | |
Ti.API.debug("cc2541_btle: getBarPressureValue(), c2 = "+c2); | |
Ti.API.debug("cc2541_btle: getBarPressureValue(), c3 = "+c3); | |
Ti.API.debug("cc2541_btle: getBarPressureValue(), c4 = "+c4); | |
Ti.API.debug("cc2541_btle: getBarPressureValue(), c5 = "+c5); | |
Ti.API.debug("cc2541_btle: getBarPressureValue(), c6 = "+c6); | |
Ti.API.debug("cc2541_btle: getBarPressureValue(), c7 = "+c7); | |
Ti.API.debug("cc2541_btle: getBarPressureValue(), c8 = "+c8); | |
Ti.API.debug("cc2541_btle: getBarPressureValue(), buffer.length = "+buffer.length); | |
if (buffer.length < 4) { | |
Ti.API.debug('cc2541_btle: getBarPressureValue(), Invalid pressure values.'); | |
return -1; | |
} | |
// var Pr = Ti.Codec.decodeNumber({ | |
// source: buffer, | |
// position: 0, | |
// type: Ti.Codec.TYPE_SHORT, | |
// byteOrder: Ti.Codec.LITTLE_ENDIAN | |
// }); | |
// var Tr = Ti.Codec.decodeNumber({ | |
// source: buffer, | |
// position: 2, | |
// type: Ti.Codec.TYPE_SHORT, | |
// byteOrder: Ti.Codec.LITTLE_ENDIAN | |
// }); | |
// var Pr = twosComp(buffer[2] + 256 * buffer[3], 16); | |
// var Tr = twosComp(buffer[0] + 256 * buffer[1], 16); | |
var Pr = buffer[2] + 256 * buffer[3]; | |
var Tr = buffer[0] + 256 * buffer[1]; | |
Ti.API.debug('cc2541_btle: getBarPressureValue(), raw temp = '+Tr); | |
Ti.API.debug('cc2541_btle: getBarPressureValue(), raw pressure = '+Pr); | |
//http://processors.wiki.ti.com/index.php/SensorTag_User_Guide#Barometric_Pressure_Sensor | |
/* Conversion algorithm for barometer pressure (hPa) | |
* | |
* Formula from application note, rev_X: | |
* Sensitivity = (c3 + ((c4 * Tr) / 2^17) + ((c5 * Tr^2) / 2^34)) | |
* Offset = (c6 * 2^14) + ((c7 * Tr) / 2^3) + ((c8 * Tr^2) / 2^19) | |
* Pa = (Sensitivity * Pr + Offset) / 2^14 | |
*/ | |
var S = (c3 + ((c4*Tr)/131072) + ((c5*Tr*Tr)/17179869184)); | |
var O = (c6*16384) + ((c7*Tr)/8) + ((c8*Tr*Tr)/524288); | |
var Pa = (S*Pr+O)/16384; | |
return Pa/139.12; | |
// return Pa; | |
} | |
function getBarPressureValue_(buffer, calibrationVal) { | |
Ti.API.debug("cc2541_btle: getBarPressureValue()"); | |
var c0 = buildCalibrationInt(calibrationVal[0], calibrationVal[1]); | |
var c1 = buildCalibrationInt(calibrationVal[2], calibrationVal[3]); | |
var c2 = buildCalibrationInt(calibrationVal[4], calibrationVal[5]); | |
var c3 = buildCalibrationInt(calibrationVal[6], calibrationVal[7]); | |
var c4 = twosComp(buildCalibrationInt(calibrationVal[8], calibrationVal[9]),16); | |
var c5 = twosComp(buildCalibrationInt(calibrationVal[10], calibrationVal[11]),16); | |
var c6 = twosComp(buildCalibrationInt(calibrationVal[12], calibrationVal[13]),16); | |
var c7 = twosComp(buildCalibrationInt(calibrationVal[14], calibrationVal[15]),16); | |
Ti.API.debug("cc2541_btle: getBarPressureValue(), c0 = "+c0); | |
Ti.API.debug("cc2541_btle: getBarPressureValue(), c1 = "+c1); | |
Ti.API.debug("cc2541_btle: getBarPressureValue(), c2 = "+c2); | |
Ti.API.debug("cc2541_btle: getBarPressureValue(), c3 = "+c3); | |
Ti.API.debug("cc2541_btle: getBarPressureValue(), c4 = "+c4); | |
Ti.API.debug("cc2541_btle: getBarPressureValue(), c5 = "+c5); | |
Ti.API.debug("cc2541_btle: getBarPressureValue(), c6 = "+c6); | |
Ti.API.debug("cc2541_btle: getBarPressureValue(), c7 = "+c7); | |
Ti.API.debug("cc2541_btle: getBarPressureValue(), buffer.length = "+buffer.length); | |
if (buffer.length < 4) { | |
Ti.API.debug('cc2541_btle: getBarPressureValue(), Invalid pressure values.'); | |
return -1; | |
} | |
var t_r = Ti.Codec.decodeNumber({ | |
source: buffer, | |
position: 2, | |
type: Ti.Codec.TYPE_SHORT, | |
byteOrder: Ti.Codec.LITTLE_ENDIAN | |
}); | |
var p_r = Ti.Codec.decodeNumber({ | |
source: buffer, | |
position: 0, | |
type: Ti.Codec.TYPE_SHORT, | |
byteOrder: Ti.Codec.LITTLE_ENDIAN | |
}); | |
Ti.API.debug('cc2541_btle: getBarPressureValue(), raw temp = '+t_r); | |
Ti.API.debug('cc2541_btle: getBarPressureValue(), raw pressure = '+p_r); | |
//http://processors.wiki.ti.com/index.php/SensorTag_User_Guide#Barometric_Pressure_Sensor | |
var t_a = (100*((c0*t_r/256) + (c1*64)))/65536; | |
var S = c2 + (c3*t_r/131072) + ((c4*t_r/32768)*t_r)/524288; | |
var O = c5*16384 + (c6*t_r/8) + ((c7*t_r/32768)*t_r)/16; | |
var p_a = (S*p_r+O)/16384; | |
//return p_a/310.228; // off by a factor of 310 | |
return p_a; | |
} | |
function getHumidityValue(buffer) { | |
Ti.API.debug("cc2541_btle: getHumidityValue()"); | |
var V; | |
if (buffer.length < 4) { | |
Ti.API.debug('cc2541_btle: Invalid humidity values.'); | |
return -1; | |
} | |
var humidity = twosComp(buffer[2] + 256 * buffer[3], 16); | |
humidity = humidity & ~0x0003; | |
v = -6.0 + humidity*125.0/65536; | |
return Math.abs(v); | |
} | |
function getTemperatureValues(buffer) { | |
Ti.API.debug("cc2541_btle: getTemperatureValues()"); | |
// Self-explanatory calculation courtesy of Texas Instrument | |
var ambTemp, objTemp, Vobj2, Tdie2, S0, a1, a2, b0, b1, b2, | |
c2, Tref, S, Vos, fObj, Tobj; | |
if (buffer.length < 4) { | |
Ti.API.debug('Invalid temperature values.'); | |
return -1; | |
} | |
objTemp = twosComp(buffer[0] + 256 * buffer[1], 16); | |
ambTemp = twosComp(buffer[2] + 256 * buffer[3], 16) / 128.0; | |
Vobj2 = objTemp * 0.00000015625; | |
Tdie2 = ambTemp + 273.15; | |
S0 = 6.4 * Math.pow(10,-14); | |
a1 = 1.75 * Math.pow(10,-3); | |
a2 = -1.678 * Math.pow(10,-5); | |
b0 = -2.94 * Math.pow(10,-5); | |
b1 = -5.7 * Math.pow(10,-7); | |
b2 = 4.63 * Math.pow(10,-9); | |
c2 = 13.4; | |
Tref = 298.15; | |
S = S0*(1+a1*(Tdie2 - Tref)+a2 * Math.pow((Tdie2 - Tref),2)); | |
Vos = b0 + b1*(Tdie2 - Tref) + b2 * Math.pow((Tdie2 - Tref),2); | |
fObj = (Vobj2 - Vos) + c2 * Math.pow((Vobj2 - Vos),2); | |
Tobj = Math.pow(Math.pow(Tdie2,4) + (fObj/S), 0.25); | |
Tobj = Tobj - 273.15; | |
//ambTemp = 32+ambTemp*9/5; | |
//objTemp = 32+objTemp*9/5; | |
return { | |
ambTemp: Math.round(ambTemp *100) / 100.0, | |
objTemp: Math.round(Tobj * 100) / 100.0 | |
}; | |
} | |
function iosCentralStateChangeCallback(e) { | |
Ti.API.debug("cc2541_btle: iosCentralStateChangeCallback()"); | |
switch (e.state) { | |
case BluetoothLE.CENTRAL_MANAGER_STATE_UNKNOWN: | |
if (centralErrorCallback) { | |
centralErrorCallback('Bluetooth LE state is resetting.'); | |
} | |
break; | |
case BluetoothLE.CENTRAL_MANAGER_STATE_RESETTING: | |
if (centralErrorCallback) { | |
centralErrorCallback('Bluetooth LE is resetting.'); | |
} | |
break; | |
case BluetoothLE.CENTRAL_MANAGER_STATE_UNSUPPORTED: | |
if (centralErrorCallback) { | |
centralErrorCallback('Bluetooth LE is not supported.'); | |
} | |
break; | |
case BluetoothLE.CENTRAL_MANAGER_STATE_UNAUTHORIZED: | |
if (centralErrorCallback) { | |
centralErrorCallback('Bluetooth LE is not authorized.'); | |
} | |
break; | |
case BluetoothLE.CENTRAL_MANAGER_STATE_POWERED_OFF: | |
if (centralOffCallback) { | |
centralOffCallback(); | |
} | |
break; | |
case BluetoothLE.CENTRAL_MANAGER_STATE_POWERED_ON: | |
if (centralOnCallback) { | |
centralOnCallback(); | |
} | |
break; | |
} | |
} | |
function androidCentralStateChangeCallback(e) { | |
Ti.API.debug("cc2541_btle: androidCentralStateChangeCallback()"); | |
switch (e.state) { | |
case BluetoothLE.STATE_TURNING_OFF: | |
Ti.API.debug('Bluetooth is turning off.'); | |
if (centralOffCallback) { | |
centralOffCallback(); | |
} | |
break; | |
case BluetoothLE.STATE_OFF: | |
break; | |
case BluetoothLE.STATE_TURNING_ON: | |
break; | |
case BluetoothLE.STATE_ON: | |
if (centralOnCallback) { | |
centralOnCallback(); | |
} | |
break; | |
} | |
} | |
function initBluetoothCentral(params) { | |
Ti.API.debug("cc2541_btle: initBluetoothCentral()"); | |
centralErrorCallback = params.errorCallback; | |
centralOffCallback = params.offCallback; | |
centralOnCallback = params.onCallback; | |
if (!centralStateChangeCallbackAdded) { | |
centralStateChangeCallbackAdded = true; | |
if (OS_ANDROID) { | |
BluetoothLE.addEventListener( | |
'stateChanged', androidCentralStateChangeCallback); | |
} else { | |
BluetoothLE.addEventListener( | |
'centralManagerStateChange', iosCentralStateChangeCallback); | |
} | |
} | |
if (OS_ANDROID) { | |
if (BluetoothLE.isSupported()) { | |
Ti.API.debug('Bluetooth is supported!'); | |
if (BluetoothLE.isEnabled()) { | |
Ti.API.debug('Bluetooth is already enabled!'); | |
params.onCallback(); | |
} else { | |
Ti.API.debug('Bluetooth is disbled; enabling now.'); | |
// This will eventually fire a stateChanged event with state set to | |
// STATE_ON, at which point we start the scanning. | |
BluetoothLE.enable(); | |
} | |
} else { | |
params.errorCallback('Bluetooth LE is not supported.'); | |
} | |
} else { | |
BluetoothLE.initCentralManager({ | |
restoreIdentifier: params.restoreIdentifier, | |
// If you set this to false, the user won't be notified if Bluetooth | |
// is off -- and you will receive CENTRAL_MANAGER_STATE_POWERED_OFF | |
// status event instead of CENTRAL_MANAGER_STATE_POWERED_ON. | |
showPowerAlert: true | |
}); | |
} | |
}; | |
function shutdownBluetoothCentral(params) { | |
Ti.API.debug("cc2541_btle: shutdownBluetoothCentral()"); | |
BluetoothLE.stopScan(); | |
if (OS_ANDROID) { | |
BluetoothLE.disable(); | |
} else { | |
BluetoothLE.releaseCentralManager(); | |
} | |
}; | |
function expandUUID(uuid) { | |
Ti.API.debug("cc2541_btle: expandUUID()"); | |
var result; | |
if (uuid.length === 4) { | |
result = BASE_UUID.substring(0, 4) + uuid + | |
BASE_UUID.substring(8, BASE_UUID.length); | |
} else { | |
result = uuid; | |
} | |
return result; | |
} | |
function uuidMatch(uuid1, uuid2) { | |
Ti.API.debug("cc2541_btle: uuidMatch()"); | |
return expandUUID(uuid1).toLowerCase() === expandUUID(uuid2).toLowerCase(); | |
} | |
function canSubscribeTo(characteristic) { | |
Ti.API.debug("cc2541_btle: canSubscribeTo()"); | |
return characteristic.properties & BluetoothLE.CHAR_PROP_NOTIFY || | |
characteristic.properties & BluetoothLE.CHAR_PROP_INDICATE; | |
} | |
function cancelConnection() { | |
Ti.API.debug("cc2541_btle: cancelConnection()"); | |
if (connectedPeripheral) { | |
Ti.API.debug('cc2541_btle: Cancelling previous connection.'); | |
BluetoothLE.cancelPeripheralConnection(connectedPeripheral); | |
connectedPeripheral = null; | |
} | |
} | |
BluetoothLE.addEventListener('moduleReady', function(e) { | |
Ti.API.debug("cc2541_btle: BluetoothLE moduleReady event"); | |
BTReady = true; | |
initBluetoothCentral({ | |
onCallback: function() { | |
startScan(); | |
}, | |
offCallback: function() { | |
stopScan(); | |
cancelConnection(); | |
}, | |
errorCallback: function(desc) { | |
Ti.API.debug(desc); | |
} | |
}); | |
}); | |
BluetoothLE.addEventListener('discoveredPeripheral', function(e) { | |
Ti.API.debug("cc2541_btle: BluetoothLE discoveredPeripheral event, e = "+JSON.stringify(e)); | |
if (e.peripheral.name !== 'TI BLE Sensor Tag' && | |
e.peripheral.name !== 'SensorTag') | |
{ | |
Ti.API.debug('Name of peripheral (' + | |
e.peripheral.name + ') does not match!'); | |
return; | |
} | |
if (!connectedPeripheral) { | |
Ti.API.debug('cc2541_btle: Discovered peripheral: ' + | |
e.peripheral.name + '/' + e.peripheral.address); | |
stopScan(); | |
BluetoothLE.connectPeripheral({ | |
peripheral: e.peripheral, | |
autoConnect: false | |
}); | |
} else { | |
Ti.API.debug('cc2541_btle: Received discoveredPeripheral event for previously discovered peripheral.'); | |
} | |
}); | |
var digestServices = function(e) { | |
Ti.API.debug("cc2541_btle: digestServices, services = "); | |
var services = e.source.services; | |
if (!services) { | |
return; | |
} | |
Ti.API.debug('Peripheral has ' + services.length + ' services'); | |
services.forEach(function(service) { | |
Ti.API.debug('cc2541_btle: digestServices Discovered service ' + service.UUID); | |
if (uuidMatch(service.UUID, IR_TEMP_SERVICE_UUID)) { | |
Ti.API.debug('cc2541_btle: digestServices Found IR temperature service!'); | |
e.source.discoverCharacteristics({ | |
service: service | |
}); | |
} else if (uuidMatch(service.UUID, HUMIDITY_SERVICE_UUID)) { | |
Ti.API.debug('cc2541_btle: digestServices Found Humidity service!'); | |
e.source.discoverCharacteristics({ | |
service: service | |
}); | |
} else if (uuidMatch(service.UUID, BARPRESSURE_SERVICE_UUID)) { | |
Ti.API.debug('cc2541_btle: digestServices Found Barometric Pressure service!'); | |
e.source.discoverCharacteristics({ | |
service: service | |
}); | |
} else if (uuidMatch(service.UUID, KEY_SERVICE_UUID)) { | |
Ti.API.debug('cc2541_btle: digestServices Found key service!'); | |
e.source.discoverCharacteristics({ | |
service: service | |
}); | |
} | |
}); | |
}; | |
var digestCharacteristics = function(e) { | |
Ti.API.debug("cc2541_btle: digestCharacteristics"); | |
var characteristics; | |
if (e.errorCode !== undefined) { | |
Ti.API.debug('cc2541_btle: digestCharacteristics Error while discovering characteristics: ' + | |
e.errorCode + '/' + e.errorDomain + '/' + | |
e.errorDescription); | |
return; | |
} | |
characteristics = e.service.characteristics; | |
characteristics.forEach(function(characteristic) { | |
Ti.API.debug('cc2541_btle: digestCharacteristics characteristic.UUID: ' + characteristic.UUID); | |
if (uuidMatch(characteristic.UUID, IR_TEMP_CONFIG_CHAR_UUID)) { | |
Ti.API.debug('cc2541_btle: digestCharacteristics Found IR temperature config characteristic, will write...'); | |
connectedPeripheral.writeValueForCharacteristic({ | |
data: Ti.createBuffer({ value: 0x01, type: Ti.Codec.TYPE_BYTE}), | |
characteristic: characteristic, | |
type: BluetoothLE.CHARACTERISTIC_TYPE_WRITE_WITH_RESPONSE | |
}); | |
} else if (uuidMatch(characteristic.UUID, IR_TEMP_DATA_CHAR_UUID)) { | |
if (canSubscribeTo(characteristic)) { | |
Ti.API.debug('cc2541_btle: digestCharacteristics Found IR temperature data characteristic, will subscribe...'); | |
connectedPeripheral.subscribeToCharacteristic(characteristic); | |
} else { | |
Ti.API.debug('cc2541_btle: digestCharacteristics Found IR temperature data characteristic but can\'t subscribe...'); | |
} | |
} else if (uuidMatch(characteristic.UUID, HUMIDITY_CONFIG_CHAR_UUID)) { | |
Ti.API.debug('cc2541_btle: digestCharacteristics Found Humidity config characteristic, will write...'); | |
connectedPeripheral.writeValueForCharacteristic({ | |
data: Ti.createBuffer({ value: 0x01, type: Ti.Codec.TYPE_BYTE}), | |
characteristic: characteristic, | |
type: BluetoothLE.CHARACTERISTIC_TYPE_WRITE_WITH_RESPONSE | |
}); | |
} else if (uuidMatch(characteristic.UUID, HUMIDITY_DATA_CHAR_UUID)) { | |
if (canSubscribeTo(characteristic)) { | |
Ti.API.debug('cc2541_btle: digestCharacteristics Found Humidity data characteristic, will subscribe...'); | |
connectedPeripheral.subscribeToCharacteristic(characteristic); | |
} else { | |
Ti.API.debug('cc2541_btle: digestCharacteristics Found Humidity data characteristic but can\'t subscribe...'); | |
} | |
} else if (uuidMatch(characteristic.UUID, BARPRESSURE_CONFIG_CHAR_UUID)) { | |
Ti.API.debug('cc2541_btle: digestCharacteristics Found Barometric Pressure config characteristic, will write 1...'); | |
connectedPeripheral.writeValueForCharacteristic({ | |
data: Ti.createBuffer({ value: 0x01, type: Ti.Codec.TYPE_BYTE}), | |
characteristic: characteristic, | |
type: BluetoothLE.CHARACTERISTIC_TYPE_WRITE_WITH_RESPONSE | |
}); | |
// get calibration data - http://www.byteworks.us/Byte_Works/Blog/Entries/2012/10/31_Accessing_the_Bluetooth_low_energy_Barometer_on_the_TI_SensorTag.html | |
Ti.API.debug('cc2541_btle: digestCharacteristics Found Barometric Pressure config characteristic, will write 2...'); | |
connectedPeripheral.writeValueForCharacteristic({ | |
data: Ti.createBuffer({ value: 0x02, type: Ti.Codec.TYPE_BYTE}), | |
characteristic: characteristic, | |
type: BluetoothLE.CHARACTERISTIC_TYPE_WRITE_WITH_RESPONSE | |
}); | |
} else if (uuidMatch(characteristic.UUID, BARPRESSURE_DATA_CHAR_UUID)) { | |
if (canSubscribeTo(characteristic)) { | |
Ti.API.debug('cc2541_btle: digestCharacteristics Found Barometric Pressure data characteristic, will subscribe...'); | |
connectedPeripheral.subscribeToCharacteristic(characteristic); | |
} else { | |
Ti.API.debug('cc2541_btle: digestCharacteristics Found Barometric Pressure data characteristic but can\'t subscribe...'); | |
} | |
} else if (uuidMatch(characteristic.UUID, BARPRESSURE_CALIBRATION_CHAR_UUID)) { | |
// get calibration data - http://www.byteworks.us/Byte_Works/Blog/Entries/2012/10/31_Accessing_the_Bluetooth_low_energy_Barometer_on_the_TI_SensorTag.html | |
Ti.API.debug('cc2541_btle: digestCharacteristics Found Barometric Pressure calibration characteristic, will read...'); | |
connectedPeripheral.readValueForCharacteristic(characteristic); | |
} else if (uuidMatch(characteristic.UUID, KEY_DATA_UUID)) { | |
if (canSubscribeTo(characteristic)) { | |
Ti.API.debug('cc2541_btle: digestCharacteristics Found key data characteristic, will subscribe...'); | |
connectedPeripheral.subscribeToCharacteristic(characteristic); | |
} else { | |
Ti.API.debug('cc2541_btle: digestCharacteristics Found key data characteristic but can\'t subscribe...'); | |
} | |
} | |
}); | |
}; | |
var digestNewCharValue = function(e) { | |
Ti.API.debug("cc2541_btle: digestNewCharValue"); | |
var tempValues; | |
var humidityValue; | |
var barPressureVal; | |
if (e.characteristic) { | |
if (e.errorCode !== undefined) { | |
Ti.API.debug('cc2541_btle: digestNewCharValue - Error while reading char ' + e.characteristic.UUID + ' ' + | |
e.errorCode + '/' + e.errorDomain + '/' + | |
e.errorDescription); | |
} else { | |
if (uuidMatch(e.characteristic.UUID, IR_TEMP_DATA_CHAR_UUID)) { | |
tempValues = getTemperatureValues(e.characteristic.value); | |
Ti.API.debug('cc2541_btle: digestNewCharValue - Ambient temperature: ' + tempValues.ambTemp); | |
Ti.API.debug('cc2541_btle: digestNewCharValue - Object temperature: ' + tempValues.objTemp); | |
if(callback) {callback({ | |
code: "tempVal", | |
value: tempValues.ambTemp | |
});} | |
} else if (uuidMatch(e.characteristic.UUID, HUMIDITY_DATA_CHAR_UUID)) { | |
Ti.API.debug('cc2541_btle: digestNewCharValue - Humidity (Raw value): ' + e.characteristic.value); | |
humidityValue = getHumidityValue(e.characteristic.value); | |
Ti.API.debug('cc2541_btle: digestNewCharValue - Humidity: ' + humidityValue); | |
if(callback) {callback({ | |
code: "humidityVal", | |
value: humidityValue | |
});} | |
} else if (uuidMatch(e.characteristic.UUID, BARPRESSURE_DATA_CHAR_UUID)) { | |
Ti.API.debug('cc2541_btle: digestNewCharValue - Barometric Pressure (Raw value): ' + e.characteristic.value); | |
if(BarometricPressureCalibrationValue){ | |
barPressureVal = getBarPressureValue(e.characteristic.value, BarometricPressureCalibrationValue); | |
Ti.API.debug('cc2541_btle: digestNewCharValue - Barometric Pressure: ' + barPressureVal); | |
if(callback) {callback({ | |
code: "pressureVal", | |
value: barPressureVal | |
});} | |
} | |
} else if (uuidMatch(e.characteristic.UUID, BARPRESSURE_CALIBRATION_CHAR_UUID)) { | |
Ti.API.debug('cc2541_btle: digestNewCharValue - Barometric Pressure Calibration (Raw value): ' + e.characteristic.value); | |
BarometricPressureCalibrationValue = e.characteristic.value; | |
Ti.API.debug('cc2541_btle: digestNewCharValue - Barometric Pressure Calibration (Raw value) length: ' + e.characteristic.value.length); | |
} else if (uuidMatch(e.characteristic.UUID, KEY_DATA_UUID)) { | |
Ti.API.debug('cc2541_btle: digestNewCharValue - KEY_DATA_UUID received, e.characteristic.value[0] = '+e.characteristic.value[0]); | |
} else { | |
Ti.API.debug('cc2541_btle: digestNewCharValue - Received value for char ' + e.characteristic.UUID.toLowerCase() + | |
': ' + e.characteristic.value); | |
} | |
} | |
} else { | |
Ti.API.debug('cc2541_btle: digestNewCharValue - Received updatedValueForCharacteristic event without characteristic object.'); | |
if (e.errorCode) { | |
Ti.API.debug('cc2541_btle: digestNewCharValue - Error while reading char: ' + | |
e.errorCode + '/' + e.errorDomain + '/' + | |
e.errorDescription); | |
} | |
} | |
}; | |
BluetoothLE.addEventListener('connectedPeripheral', function(e) { | |
Ti.API.debug("cc2541_btle: BluetoothLE connectedPeripheral event, name = "+e.peripheral.name+", address = "+e.peripheral.address); | |
Ti.API.debug("cc2541_btle: BluetoothLE connectedPeripheral event, e = "+JSON.stringify(e)); | |
if (connectedPeripheral && !connectedPeripheral.equals(e.peripheral)) { | |
cancelConnection(); | |
} | |
if(callback) {callback({ | |
code: "connected" | |
});} | |
connectedPeripheral = e.peripheral; | |
connectedPeripheral.discoverServices(); | |
connectedPeripheral.addEventListener('discoveredServices', digestServices); | |
connectedPeripheral.addEventListener('discoveredCharacteristics', digestCharacteristics); | |
connectedPeripheral.addEventListener('updatedValueForCharacteristic', digestNewCharValue); | |
}); | |
BluetoothLE.addEventListener('failedToConnectPeripheral', function(e) { | |
Ti.API.debug("cc2541_btle: BluetoothLE failedToConnectPeripheral event"); | |
}); | |
BluetoothLE.addEventListener('disconnectedPeripheral', function(e) { | |
Ti.API.debug("cc2541_btle: BluetoothLE disconnectedPeripheral event"); | |
if(callback) {callback({ | |
code: "disconnected" | |
});} | |
if (connectedPeripheral) { | |
connectedPeripheral.removeEventListener( | |
'discoveredServices', digestServices); | |
connectedPeripheral.removeEventListener( | |
'discoveredCharacteristics', digestCharacteristics); | |
connectedPeripheral.removeEventListener( | |
'updatedValueForCharacteristic', digestNewCharValue); | |
} | |
}); | |
function startScan() { | |
Ti.API.debug('cc2541_btle: startScan(), scanRunning = '+scanRunning); | |
if (!scanRunning) { | |
scanRunning = true; | |
cancelConnection(); | |
BluetoothLE.startScan(); | |
} | |
} | |
function stopScan() { | |
Ti.API.debug('cc2541_btle: stopScan(), scanRunning = '+scanRunning); | |
BluetoothLE.stopScan(); | |
Ti.API.debug('Stopped scanning.'); | |
scanRunning = false; | |
} | |
exports.init = function(_callback) { | |
callback = _callback; | |
}; | |
exports.scanStart = function() { | |
Ti.API.debug('cc2541_btle: scanStart()'); | |
startScan(); | |
}; | |
exports.scanStop = function() { | |
Ti.API.debug('cc2541_btle: scanStop()'); | |
cancelConnection(); | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"global": { | |
"theme":"whitetheme" | |
}, | |
"env:development": {}, | |
"env:test": {}, | |
"env:production": {}, | |
"os:android": {}, | |
"os:blackberry": {}, | |
"os:ios": {}, | |
"os:mobileweb": {}, | |
"dependencies": {} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var bt = require('cc2541_btle'); | |
var animationDuration = 300; | |
var waitDuration = 3000; | |
var connectionWaitDuration = 15000; | |
var myTimeout, connectionTimeout, titleViewOn=true; | |
var isBtConnected = false; | |
var connectSound = "/audio/ding1.mp3"; | |
var disconnectSound = "/audio/FoleySwitchMetalSwitch1.mp3"; | |
function startConnectionTimer() { | |
Ti.API.debug("index: startConnectionTimer"); | |
connectionTimeout = setTimeout(displayConnectionWarning, connectionWaitDuration); | |
} | |
function displayConnectionWarning() { | |
Ti.API.debug("index: displayConnectionWarning"); | |
$.activityIndicator.hide(); | |
$.activityIndicatorVw.visible=false; | |
alert("SensorTag not found\n\nPlease turn SensorTag on."); | |
} | |
function settingsBtnClick(e) { | |
Ti.API.debug("index: settingsBTNClick"); | |
animateTitleOut(); | |
var infoController = Alloy.createController('info',{}).getView().open(); | |
} | |
function connectBtnClick(e) { | |
Ti.API.debug("index: connectBtnClick, isBtConnected = "+isBtConnected); | |
if(isBtConnected) { | |
bt.scanStop(); | |
} else { | |
bt.scanStart(); | |
startConnectionTimer(); | |
$.activityIndicator.show(); | |
$.activityIndicatorVw.visible = true; | |
} | |
} | |
function animateTitleOut(){ | |
var animation = Titanium.UI.createAnimation({ | |
curve: Titanium.UI.ANIMATION_CURVE_EASE_IN, | |
duration: animationDuration | |
}); | |
animation.top = -$.titleVw.height; | |
animation.addEventListener('complete',function(){ | |
titleViewOn = false; | |
}); | |
$.titleVw.animate(animation); | |
} | |
function animateTitleIn(){ | |
var animation = Titanium.UI.createAnimation({ | |
curve: Titanium.UI.ANIMATION_CURVE_EASE_IN, | |
duration: animationDuration | |
}); | |
animation.top = 0; | |
animation.addEventListener('complete',function(){ | |
titleViewOn = true; | |
myTimeout = setTimeout(animateTitleOut, 2*waitDuration); | |
}); | |
$.titleVw.animate(animation); | |
} | |
$.mainVw.addEventListener('click', function(e) { | |
Ti.API.debug("index: mainVw click event heard"); | |
clearTimeout(myTimeout); | |
if(titleViewOn) { | |
animateTitleOut(); | |
} else { | |
animateTitleIn(); | |
} | |
}); | |
function btConnected() { | |
Ti.API.debug("index: btConnected"); | |
isBtConnected = true; | |
$.connectBtn.backgroundImage = "/images/connected.png"; | |
$.footerIv.image = "/images/connected_footer.png"; | |
} | |
function btDisconnected() { | |
Ti.API.debug("index: btDisconnected"); | |
isBtConnected = false; | |
$.connectBtn.backgroundImage = "/images/disconnected.png"; | |
$.footerIv.image = "/images/disconnected_footer.png"; | |
} | |
function btResponseHandler(e) { | |
Ti.API.debug("index: btResponseHandler, e = "+JSON.stringify(e)); | |
switch (e.code) { | |
case "tempVal": | |
if(Alloy.Globals.farenheitOn){ | |
var fvalue = 32+((e.value*9)/5); | |
$.tempRow.setWeatherItemValueText(fvalue.toFixed(1)+"\u00B0"+"F"); | |
} else { | |
$.tempRow.setWeatherItemValueText(e.value.toFixed(1)+"\u00B0"+"C"); | |
} | |
break; | |
case "humidityVal": | |
$.humidityRow.setWeatherItemValueText(e.value.toFixed(1)+"%"); | |
break; | |
case "pressureVal": | |
$.pressureRow.setWeatherItemValueText(e.value.toFixed(1)); | |
break; | |
case "connected": | |
if(Alloy.Globals.audioOn){ | |
var player = Ti.Media.createSound({url: connectSound}); | |
player.play(); | |
} | |
btConnected(); | |
clearTimeout(connectionTimeout); | |
$.activityIndicator.hide(); | |
$.activityIndicatorVw.visible=false; | |
break; | |
case "disconnected": | |
if(Alloy.Globals.audioOn){ | |
var player = Ti.Media.createSound({url: disconnectSound}); | |
player.play(); | |
} | |
btDisconnected(); | |
break; | |
} | |
} | |
myTimeout = setTimeout(animateTitleOut, waitDuration); | |
startConnectionTimer(); | |
if ((Ti.Platform.osname === 'android' && Ti.Platform.version >= '4.3') || | |
((Ti.Platform.osname === 'iphone' || Ti.Platform.osname === 'ipad') && | |
Ti.Platform.version >= '5.0')) { | |
bt.init(btResponseHandler); | |
} else { | |
alert("This application only runs on devices with Bluetooth capabilites."); | |
} | |
$.index.open(); | |
$.activityIndicator.show(); | |
$.activityIndicatorVw.visible=true; | |
(function(){ | |
var props = Ti.App.Properties.listProperties(); | |
Ti.API.debug("props = "+props); | |
Ti.API.debug("props.length = "+props.length); | |
for (var i=0, ilen=props.length; i<ilen; i++){ | |
var value = Ti.App.Properties.getString(props[i]); | |
Ti.API.debug(props[i] + ' = ' + value); | |
if(props[i]==='farenheitOn'){ | |
value = Ti.App.Properties.getBool(props[i]); | |
Ti.API.debug('farenheitOn = ' + value); | |
Alloy.Globals.farenheitOn = value; | |
} else if(props[i]==='audioOn'){ | |
value = Ti.App.Properties.getBool(props[i]); | |
Ti.API.info('audioOn = ' + value); | |
Alloy.Globals.audioOn = value; | |
} else if(props[i]==='didRunAlready'){ | |
Alloy.Globals.firstRun = false; | |
} | |
} | |
if(Alloy.Globals.firstRun) { | |
Ti.App.Properties.setBool('didRunAlready', true); | |
alert("My Weather Station requires a Texas Insruments CC2541 SensorTag.\n\nThis message only appears once."); | |
} | |
})(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
".container": { | |
backgroundColor:"white", | |
fullscreen: true, | |
navBarHidden: true | |
} | |
"Label": { | |
width: Ti.UI.SIZE, | |
height: Ti.UI.SIZE, | |
color: "#000", | |
font: { | |
fontFamily: 'Roboto-Regular' | |
} | |
} | |
"#titleVw": { | |
height: 44, | |
backgroundColor: "#f8f8f8", | |
zIndex: 2, | |
top: 0 | |
} | |
"#titleVwLbl": { | |
color: "black", | |
font: { | |
fontSize: 18, | |
fontFamily: 'Roboto-Regular' | |
} | |
} | |
"#mainVw": { | |
height: Ti.UI.FILL, | |
backgroundColor: "#ededed", | |
layout: "vertical" | |
} | |
".titleVwBtn": { | |
width: 38, | |
height: 33 | |
} | |
"#connectBtn": { | |
backgroundImage: "/images/disconnected.png", | |
left: 5 | |
} | |
"#settingsBtn": { | |
backgroundImage: "/images/settings.png", | |
right: 5 | |
} | |
".separatorSpaceVw": { | |
height: "5%" | |
} | |
"#headerSpaceVW": { | |
height: 50 | |
} | |
".footerVW": { | |
height: 50 | |
} | |
"#footerVwLbl": { | |
right: 10, | |
bottom: 2, | |
color: "black", | |
font: { | |
fontSize: 12, | |
fontFamily: 'Roboto-Thin' | |
} | |
} | |
"#footerIv": { | |
image: "/images/disconnected_footer.png", | |
width: 18, | |
height: 18, | |
left: 10, | |
bottom: 2 | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<Alloy> | |
<Window class="container"> | |
<View id="titleVw"> | |
<Button id="connectBtn" class="titleVwBtn" onClick="connectBtnClick" /> | |
<Label id="titleVwLbl">My Weather Station</Label> | |
<Button id="settingsBtn" class="titleVwBtn" onClick="settingsBtnClick" /> | |
<!-- <View class="colorLineVw"/> --> | |
</View> | |
<View id="mainVw"> | |
<!-- <Label id="label" onClick="doClick">Hello, World</Label> --> | |
<View id="headerSpaceVW"/> | |
<Require src='weatherItemRow' id='tempRow' iconImage="/images/temp.png" weatherItemValueText="--.-\u00B0" title="TEMPERATURE" /> | |
<View class="separatorSpaceVw"/> | |
<Require src='weatherItemRow' id='humidityRow' iconImage="/images/humidity.png" weatherItemValueText="--.--%" title="RELATIVE HUMIDITY" /> | |
<View class="separatorSpaceVw" /> | |
<Require src='weatherItemRow' id='pressureRow' iconImage="/images/pressure.png" weatherItemValueText="----.-" title="BAROMETRIC PRESSURE" /> | |
<!-- <View class="separatorSpaceVw" /> --> | |
<View class="footerVw"> | |
<Label id="footerVwLbl">My Weather Station</Label> | |
<ImageView id="footerIv" /> | |
</View> | |
</View> | |
<View id="activityIndicatorVw" visible="false"> | |
<ActivityIndicator id="activityIndicator" message="Connecting..."/> | |
</View> | |
</Window> | |
</Alloy> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$.closeBtn.addEventListener("click", function(e) { | |
Ti.API.info("Info: Close Button click event"); | |
$.info.close(); | |
}); | |
if(Alloy.Globals.audioOn) { | |
$.audioSw.value = Alloy.Globals.audioOn; | |
} else { | |
$.audioSw.value = false; | |
} | |
if(Alloy.Globals.farenheitOn) { | |
$.farenheitSw.value = Alloy.Globals.farenheitOn; | |
} else { | |
$.farenheitSw.value = false; | |
} | |
$.farenheitSw.addEventListener('change', function(e){ | |
Ti.App.Properties.setString('farenheitOn', $.farenheitSw.value); | |
Alloy.Globals.farenheitOn = $.farenheitSw.value; | |
}); | |
$.audioSw.addEventListener('change', function(e){ | |
Ti.App.Properties.setString('audioOn', $.audioSw.value); | |
Alloy.Globals.audioOn = $.audioSw.value; | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"#info": { | |
backgroundColor:"white", | |
fullscreen: true, | |
navBarHidden: true | |
} | |
"#titleVw": { | |
height: 44, | |
backgroundColor: "#f8f8f8", | |
zIndex: 2, | |
top: 0 | |
} | |
"#titleVwLbl": { | |
color: "black", | |
font: { | |
fontSize: 18, | |
fontFamily: 'Roboto-Regular' | |
} | |
} | |
"#closeBtn":{ | |
width: 32, | |
height: 32, | |
right: 5, | |
image:'/images/closeBtn.png' | |
} | |
"Label":{ | |
color: "black", | |
font: {fontFamily:'Roboto-Regular', fontSize:"14dp"} | |
} | |
".infoLabel":{ | |
top: 20, | |
color: "black", | |
height : 'auto', | |
width : '95%', | |
horizontalWrap: true, | |
textAlign:Ti.UI.TEXT_ALIGNMENT_CENTER, | |
font: {fontFamily:'Roboto-Regular', fontSize:"14dp"} | |
} | |
".infoLabelSmall":{ | |
top: 20, | |
color: "black", | |
height : 'auto', | |
width : '95%', | |
horizontalWrap: true, | |
textAlign:Ti.UI.TEXT_ALIGNMENT_CENTER, | |
font: {fontFamily:'Roboto-Regular', fontSize:"10dp"} | |
} | |
"#logoIV": { | |
//image: "/images/appc_logo_white.png", // use on dark backgrounds | |
image: "/images/appc_logo_black.png", // use on light backgrounds | |
width: 138, | |
height: 29 | |
} | |
".settingsSw": { | |
left: 5, | |
width: "50%" | |
} | |
".settingsSw[platform=android]": { | |
style: Titanium.UI.Android.SWITCH_STYLE_CHECKBOX | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<Alloy> | |
<Window class="container" id="info" modal="true"> | |
<View layout='vertical'> | |
<View id='titleVw'> | |
<ImageView id='closeBtn' /> | |
<Label id="titleVwLbl" class='titleVwLbl'>About My Weather Station</Label> | |
<View class="colorLineVw"/> | |
</View> | |
<ScrollView showVerticalScrollIndicator="false" showHorizontalScrollIndicator="false" height='Ti.UI.FILL' width='90%' layout='vertical'> | |
<Label class='infoLabel'>My Weather Station is a personal weather application that leverages the Texas Instruments CC2541 Bluetooh LE SensorTag \n\nAttributions:\nLogical Labs Titanium Bluetooth LE Module\nFlatIcons - Creative Commons BY 3.0\n | |
</Label> | |
<Label class='infoLabel'>No personally identifiable information is required or collected by this application.\n</Label> | |
<Label class='infoLabel'>Powered by</Label> | |
<ImageView id="logoIV" /> | |
<Label class='infoLabelSmall'>Appcelerator® is a trademark of Appcelerator, Inc. and is used under license.\n\n</Label> | |
<View id="settings" height="Ti.UI.SIZE" layout="vertical"> | |
<View layout="horizontal" height="Ti.UI.SIZE" > | |
<View height="40" width="50%" top="5"> | |
<Label right="5">Farenheit:</Label> | |
</View> | |
<View height="40" width="45%" top="5"> | |
<Switch id="farenheitSw" class="settingsSw"></Switch> | |
</View> | |
<View height="40" width="50%" top="5"> | |
<Label right="5">Sound:</Label> | |
</View> | |
<View height="40" width="45%" top="5"> | |
<Switch id="audioSw" class="settingsSw"></Switch> | |
</View> | |
</View> | |
</View> | |
</ScrollView> | |
</View> | |
</Window> | |
</Alloy> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="UTF-8"?> | |
<ti:app xmlns:ti="http://ti.appcelerator.org"> | |
<id>com.appcelerator.mws</id> | |
<name>MWS</name> | |
<version>1.0</version> | |
<publisher>lbrenman</publisher> | |
<url>http://</url> | |
<description>undefined</description> | |
<copyright>2014 by lbrenman</copyright> | |
<icon>appicon.png</icon> | |
<fullscreen>false</fullscreen> | |
<navbar-hidden>false</navbar-hidden> | |
<analytics>true</analytics> | |
<guid>XXXXXX</guid> | |
<property name="ti.ui.defaultunit" type="string">dp</property> | |
<ios> | |
<min-ios-ver>6.0</min-ios-ver> | |
<plist> | |
<dict> | |
<key>UISupportedInterfaceOrientations~iphone</key> | |
<array> | |
<string>UIInterfaceOrientationPortrait</string> | |
</array> | |
<key>UISupportedInterfaceOrientations~ipad</key> | |
<array> | |
<string>UIInterfaceOrientationPortrait</string> | |
<string>UIInterfaceOrientationPortraitUpsideDown</string> | |
<string>UIInterfaceOrientationLandscapeLeft</string> | |
<string>UIInterfaceOrientationLandscapeRight</string> | |
</array> | |
<key>UIBackgroundModes</key> | |
<array> | |
<string>bluetooth-central</string> | |
<string>bluetooth-peripheral</string> | |
</array> | |
<key>UIRequiresPersistentWiFi</key> | |
<false/> | |
<key>UIPrerenderedIcon</key> | |
<false/> | |
<key>UIStatusBarHidden</key> | |
<false/> | |
<key>UIStatusBarStyle</key> | |
<string>UIStatusBarStyleDefault</string> | |
</dict> | |
</plist> | |
</ios> | |
<android xmlns:android="http://schemas.android.com/apk/res/android"> | |
<manifest> | |
<application android:theme="@style/Theme.NoActionBar"> | |
<activity | |
android:configChanges="keyboardHidden|orientation" | |
android:name="org.appcelerator.titanium.TiActivity" android:screenOrientation="portrait"/> | |
</application>/> | |
<uses-sdk | |
android:minSdkVersion="14" android:targetSdkVersion="19"/> | |
</manifest> | |
</android> | |
<mobileweb> | |
<precache/> | |
<splash> | |
<enabled>true</enabled> | |
<inline-css-images>true</inline-css-images> | |
</splash> | |
<theme>default</theme> | |
</mobileweb> | |
<modules> | |
<module platform="android">com.logicallabs.bluetoothle</module> | |
<module platform="iphone">com.logicallabs.bluetoothle</module> | |
</modules> | |
<deployment-targets> | |
<target device="android">true</target> | |
<target device="blackberry">false</target> | |
<target device="ipad">true</target> | |
<target device="iphone">true</target> | |
<target device="mobileweb">false</target> | |
</deployment-targets> | |
<sdk-version>3.4.0.GA</sdk-version> | |
<plugins> | |
<plugin version="1.0">ti.alloy</plugin> | |
</plugins> | |
</ti:app> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var args = arguments[0] || {}; | |
$.weatherIconIv.image = args.iconImage || "/images/temp.png"; | |
$.weatherItemLbl.text = args.weatherItemValueText || "N/A" | |
$.titleVwLbl.text = args.title || "Temperature"; | |
$.setWeatherItemValueText = function (val) { | |
$.weatherItemLbl.text = val; | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
".weatherItemVw": { | |
height: "25%", | |
//width: "95%", | |
right: 10, | |
left: 10, | |
backgroundColor: "white", | |
layout: "vertical", | |
borderWidth: 1, | |
borderColor: "#cfcfcf" | |
} | |
".titleVw": { | |
height: "40", | |
backgroundColor: "#f5f5f5" | |
} | |
".titleVwLbl": { | |
top: 10, | |
left: 5, | |
color: "#707070", | |
font: { | |
fontSize: 14, | |
fontFamily: 'Roboto-Regular' | |
} | |
} | |
".subVw": { | |
width: "50%", | |
height: Ti.UI.FILL | |
//backgroundColor: "gray" | |
} | |
"#weatherItemLbl": { | |
right: 10, | |
color: "#707070", | |
font: { | |
fontSize: 40, | |
fontFamily: 'Roboto-Regular' | |
} | |
} | |
".weatherItemIv": { | |
width: 66, | |
height: 66, | |
left: 10 | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<Alloy> | |
<View class="weatherItemVw"> | |
<View class="titleVw"> | |
<Label id="titleVwLbl" class="titleVwLbl" /> | |
</View> | |
<View layout="horizontal" height="Ti.UI.FILL"> | |
<View class="subVw"> | |
<ImageView id="weatherIconIv" class="weatherItemIv"/> | |
</View> | |
<View class="subVw"> | |
<Label id="weatherItemLbl">70F</Label> | |
</View> | |
</View> | |
</View> | |
</Alloy> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment