use of nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent in project Gadgetbridge by Freeyourgadget.
the class LiveviewProtocol method decodeResponse.
@Override
public GBDeviceEvent[] decodeResponse(byte[] responseData) {
int length = responseData.length;
if (length < 4) {
//empty message
return null;
} else {
ByteBuffer buffer = ByteBuffer.wrap(responseData, 0, length);
byte msgId = buffer.get();
buffer.get();
int payloadLen = buffer.getInt();
GBDeviceEventSendBytes reply = new GBDeviceEventSendBytes();
if (payloadLen + 6 == length) {
switch(msgId) {
case LiveviewConstants.MSG_DEVICESTATUS:
reply.encodedBytes = constructMessage(LiveviewConstants.MSG_DEVICESTATUS_ACK, new byte[] { LiveviewConstants.RESULT_OK });
break;
case LiveviewConstants.MSG_DISPLAYPANEL_ACK:
//hack to make the notifications vibrate!
reply.encodedBytes = encodeVibrateRequest((short) 100, (short) 200);
break;
default:
}
GBDeviceEventSendBytes ack = new GBDeviceEventSendBytes();
ack.encodedBytes = constructMessage(LiveviewConstants.MSG_ACK, new byte[] { msgId });
return new GBDeviceEvent[] { ack, reply };
}
}
return super.decodeResponse(responseData);
}
use of nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent in project Gadgetbridge by Freeyourgadget.
the class AppMessageHandlerZalewszczak method onAppStart.
@Override
public GBDeviceEvent[] onAppStart() {
WeatherSpec weatherSpec = Weather.getInstance().getWeatherSpec();
if (weatherSpec == null) {
return new GBDeviceEvent[] { null };
}
GBDeviceEventSendBytes sendBytes = new GBDeviceEventSendBytes();
sendBytes.encodedBytes = encodeWeatherMessage(weatherSpec);
return new GBDeviceEvent[] { sendBytes };
}
use of nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent in project Gadgetbridge by Freeyourgadget.
the class PebbleIoThread method run.
@Override
public void run() {
mIsConnected = connect();
if (!mIsConnected) {
if (GBApplication.getGBPrefs().getAutoReconnect() && !mQuit) {
gbDevice.setState(GBDevice.State.WAITING_FOR_RECONNECT);
gbDevice.sendDeviceUpdateIntent(getContext());
}
return;
}
byte[] buffer = new byte[8192];
enablePebbleKitSupport(true);
mQuit = false;
while (!mQuit) {
try {
if (mIsInstalling) {
switch(mInstallState) {
case WAIT_SLOT:
if (mInstallSlot == -1) {
// no slots available
finishInstall(true);
} else if (mInstallSlot >= 0) {
mInstallState = PebbleAppInstallState.START_INSTALL;
continue;
}
break;
case START_INSTALL:
LOG.info("start installing app binary");
PebbleInstallable pi = mPebbleInstallables[mCurrentInstallableIndex];
mFis = mPBWReader.getInputStreamFile(pi.getFileName());
mCRC = pi.getCRC();
mBinarySize = pi.getFileSize();
mBytesWritten = 0;
writeInstallApp(mPebbleProtocol.encodeUploadStart(pi.getType(), mInstallSlot, mBinarySize, mPBWReader.isLanguage() ? "lang" : null));
mAppInstallToken = -1;
mInstallState = PebbleAppInstallState.WAIT_TOKEN;
break;
case WAIT_TOKEN:
if (mAppInstallToken != -1) {
LOG.info("got token " + mAppInstallToken);
mInstallState = PebbleAppInstallState.UPLOAD_CHUNK;
continue;
}
break;
case UPLOAD_CHUNK:
int bytes = 0;
do {
int read = mFis.read(buffer, bytes, 2000 - bytes);
if (read <= 0)
break;
bytes += read;
} while (bytes < 2000);
if (bytes > 0) {
GB.updateInstallNotification(getContext().getString(R.string.installing_binary_d_d, (mCurrentInstallableIndex + 1), mPebbleInstallables.length), true, (int) (((float) mBytesWritten / mBinarySize) * 100), getContext());
writeInstallApp(mPebbleProtocol.encodeUploadChunk(mAppInstallToken, buffer, bytes));
mBytesWritten += bytes;
mAppInstallToken = -1;
mInstallState = PebbleAppInstallState.WAIT_TOKEN;
} else {
mInstallState = PebbleAppInstallState.UPLOAD_COMMIT;
continue;
}
break;
case UPLOAD_COMMIT:
writeInstallApp(mPebbleProtocol.encodeUploadCommit(mAppInstallToken, mCRC));
mAppInstallToken = -1;
mInstallState = PebbleAppInstallState.WAIT_COMMIT;
break;
case WAIT_COMMIT:
if (mAppInstallToken != -1) {
LOG.info("got token " + mAppInstallToken);
mInstallState = PebbleAppInstallState.UPLOAD_COMPLETE;
continue;
}
break;
case UPLOAD_COMPLETE:
writeInstallApp(mPebbleProtocol.encodeUploadComplete(mAppInstallToken));
if (++mCurrentInstallableIndex < mPebbleInstallables.length) {
mInstallState = PebbleAppInstallState.START_INSTALL;
} else {
mInstallState = PebbleAppInstallState.APP_REFRESH;
}
break;
case APP_REFRESH:
if (mPBWReader.isFirmware()) {
writeInstallApp(mPebbleProtocol.encodeInstallFirmwareComplete());
finishInstall(false);
} else if (mPBWReader.isLanguage() || mPebbleProtocol.mFwMajor >= 3) {
// FIXME: don't know yet how to detect success
finishInstall(false);
} else {
writeInstallApp(mPebbleProtocol.encodeAppRefresh(mInstallSlot));
}
break;
default:
break;
}
}
if (mIsTCP) {
mInStream.skip(6);
}
int bytes = readWithException(mInStream, buffer, 0, 4);
while (bytes < 4) {
bytes += readWithException(mInStream, buffer, bytes, 4 - bytes);
}
ByteBuffer buf = ByteBuffer.wrap(buffer);
buf.order(ByteOrder.BIG_ENDIAN);
short length = buf.getShort();
short endpoint = buf.getShort();
if (length < 0 || length > 8192) {
LOG.info("invalid length " + length);
while (mInStream.available() > 0) {
// read all
readWithException(mInStream, buffer, 0, buffer.length);
}
continue;
}
bytes = readWithException(mInStream, buffer, 4, length);
while (bytes < length) {
bytes += readWithException(mInStream, buffer, bytes + 4, length - bytes);
}
if (mIsTCP) {
mInStream.skip(2);
}
GBDeviceEvent[] deviceEvents = mPebbleProtocol.decodeResponse(buffer);
if (deviceEvents == null) {
LOG.info("unhandled message to endpoint " + endpoint + " (" + length + " bytes)");
} else {
for (GBDeviceEvent deviceEvent : deviceEvents) {
if (deviceEvent == null) {
continue;
}
if (!evaluateGBDeviceEventPebble(deviceEvent)) {
mPebbleSupport.evaluateGBDeviceEvent(deviceEvent);
}
}
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
} catch (IOException e) {
if (e.getMessage() != null && (e.getMessage().equals("broken pipe") || e.getMessage().contains("socket closed"))) {
//FIXME: this does not feel right
LOG.info(e.getMessage());
mIsConnected = false;
int reconnectAttempts = prefs.getInt("pebble_reconnect_attempts", 10);
if (!mQuit && GBApplication.getGBPrefs().getAutoReconnect() && reconnectAttempts > 0) {
gbDevice.setState(GBDevice.State.WAITING_FOR_RECONNECT);
gbDevice.sendDeviceUpdateIntent(getContext());
int delaySeconds = 1;
while (reconnectAttempts-- > 0 && !mQuit && !mIsConnected) {
LOG.info("Trying to reconnect (attempts left " + reconnectAttempts + ")");
mIsConnected = connect();
if (!mIsConnected) {
try {
Thread.sleep(delaySeconds * 1000);
} catch (InterruptedException ignored) {
}
if (delaySeconds < 64) {
delaySeconds *= 2;
}
}
}
}
if (!mIsConnected) {
mBtSocket = null;
LOG.info("Bluetooth socket closed, will quit IO Thread");
break;
}
}
}
}
mIsConnected = false;
if (mBtSocket != null) {
try {
mBtSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
mBtSocket = null;
}
enablePebbleKitSupport(false);
if (mQuit) {
gbDevice.setState(GBDevice.State.NOT_CONNECTED);
} else {
gbDevice.setState(GBDevice.State.WAITING_FOR_RECONNECT);
}
gbDevice.sendDeviceUpdateIntent(getContext());
}
use of nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent in project Gadgetbridge by Freeyourgadget.
the class PebbleProtocol method decodeDatalog.
private GBDeviceEvent[] decodeDatalog(ByteBuffer buf, short length) {
boolean ack = true;
byte command = buf.get();
byte id = buf.get();
GBDeviceEventDataLogging devEvtDataLogging = null;
switch(command) {
case DATALOG_TIMEOUT:
LOG.info("DATALOG TIMEOUT. id=" + (id & 0xff) + " - ignoring");
return null;
case DATALOG_SENDDATA:
buf.order(ByteOrder.LITTLE_ENDIAN);
int items_left = buf.getInt();
int crc = buf.getInt();
DatalogSession datalogSession = mDatalogSessions.get(id);
LOG.info("DATALOG SENDDATA. id=" + (id & 0xff) + ", items_left=" + items_left + ", total length=" + (length - 10));
if (datalogSession != null) {
LOG.info("DATALOG UUID=" + datalogSession.uuid + ", tag=" + datalogSession.tag + datalogSession.getTaginfo() + ", itemSize=" + datalogSession.itemSize + ", itemType=" + datalogSession.itemType);
if (!datalogSession.uuid.equals(UUID_ZERO) && datalogSession.getClass().equals(DatalogSession.class) && mEnablePebbleKit) {
devEvtDataLogging = datalogSession.handleMessageForPebbleKit(buf, length - 10);
if (devEvtDataLogging == null) {
ack = false;
}
} else {
ack = datalogSession.handleMessage(buf, length - 10);
}
}
break;
case DATALOG_OPENSESSION:
UUID uuid = getUUID(buf);
buf.order(ByteOrder.LITTLE_ENDIAN);
int timestamp = buf.getInt();
int log_tag = buf.getInt();
byte item_type = buf.get();
short item_size = buf.getShort();
LOG.info("DATALOG OPENSESSION. id=" + (id & 0xff) + ", App UUID=" + uuid.toString() + ", log_tag=" + log_tag + ", item_type=" + item_type + ", itemSize=" + item_size);
if (!mDatalogSessions.containsKey(id)) {
if (uuid.equals(UUID_ZERO) && log_tag == 81) {
mDatalogSessions.put(id, new DatalogSessionHealthSteps(id, uuid, timestamp, log_tag, item_type, item_size, getDevice()));
} else if (uuid.equals(UUID_ZERO) && log_tag == 83) {
mDatalogSessions.put(id, new DatalogSessionHealthSleep(id, uuid, timestamp, log_tag, item_type, item_size, getDevice()));
} else if (uuid.equals(UUID_ZERO) && log_tag == 84) {
mDatalogSessions.put(id, new DatalogSessionHealthOverlayData(id, uuid, timestamp, log_tag, item_type, item_size, getDevice()));
} else if (uuid.equals(UUID_ZERO) && log_tag == 85) {
mDatalogSessions.put(id, new DatalogSessionHealthHR(id, uuid, timestamp, log_tag, item_type, item_size, getDevice()));
} else {
mDatalogSessions.put(id, new DatalogSession(id, uuid, timestamp, log_tag, item_type, item_size));
}
}
break;
case DATALOG_CLOSE:
LOG.info("DATALOG_CLOSE. id=" + (id & 0xff));
datalogSession = mDatalogSessions.get(id);
if (datalogSession != null) {
if (!datalogSession.uuid.equals(UUID_ZERO) && datalogSession.getClass().equals(DatalogSession.class) && mEnablePebbleKit) {
GBDeviceEventDataLogging dataLogging = new GBDeviceEventDataLogging();
dataLogging.command = GBDeviceEventDataLogging.COMMAND_FINISH_SESSION;
dataLogging.appUUID = datalogSession.uuid;
dataLogging.tag = datalogSession.tag;
devEvtDataLogging = dataLogging;
}
mDatalogSessions.remove(id);
}
break;
default:
LOG.info("unknown DATALOG command: " + (command & 0xff));
break;
}
GBDeviceEventSendBytes sendBytes = new GBDeviceEventSendBytes();
if (ack) {
LOG.info("sending ACK (0x85)");
sendBytes.encodedBytes = encodeDatalog(id, DATALOG_ACK);
} else {
LOG.info("sending NACK (0x86)");
sendBytes.encodedBytes = encodeDatalog(id, DATALOG_NACK);
}
// append ack/nack
return new GBDeviceEvent[] { devEvtDataLogging, sendBytes };
}
use of nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent in project Gadgetbridge by Freeyourgadget.
the class AppMessageHandler method handleMessage.
public GBDeviceEvent[] handleMessage(ArrayList<Pair<Integer, Object>> pairs) {
// Just ACK
GBDeviceEventSendBytes sendBytesAck = new GBDeviceEventSendBytes();
sendBytesAck.encodedBytes = mPebbleProtocol.encodeApplicationMessageAck(mUUID, mPebbleProtocol.last_id);
return new GBDeviceEvent[] { sendBytesAck };
}
Aggregations