Search in sources :

Example 1 with GBDeviceEvent

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);
}
Also used : GBDeviceEvent(nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent) GBDeviceEventSendBytes(nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventSendBytes) ByteBuffer(java.nio.ByteBuffer)

Example 2 with GBDeviceEvent

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 };
}
Also used : GBDeviceEvent(nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent) WeatherSpec(nodomain.freeyourgadget.gadgetbridge.model.WeatherSpec) GBDeviceEventSendBytes(nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventSendBytes)

Example 3 with GBDeviceEvent

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());
}
Also used : PebbleInstallable(nodomain.freeyourgadget.gadgetbridge.devices.pebble.PebbleInstallable) GBDeviceEvent(nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent) IOException(java.io.IOException) ByteBuffer(java.nio.ByteBuffer)

Example 4 with GBDeviceEvent

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 };
}
Also used : GBDeviceEvent(nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent) GBDeviceEventDataLogging(nodomain.freeyourgadget.gadgetbridge.deviceevents.pebble.GBDeviceEventDataLogging) GBDeviceEventSendBytes(nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventSendBytes) UUID(java.util.UUID)

Example 5 with GBDeviceEvent

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 };
}
Also used : GBDeviceEvent(nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent) GBDeviceEventSendBytes(nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventSendBytes)

Aggregations

GBDeviceEvent (nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent)18 GBDeviceEventSendBytes (nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventSendBytes)15 WeatherSpec (nodomain.freeyourgadget.gadgetbridge.model.WeatherSpec)7 ByteBuffer (java.nio.ByteBuffer)4 UUID (java.util.UUID)4 IOException (java.io.IOException)3 DBHandler (nodomain.freeyourgadget.gadgetbridge.database.DBHandler)2 GBDeviceEventAppManagement (nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventAppManagement)2 JSONException (org.json.JSONException)2 JSONObject (org.json.JSONObject)2 Pair (android.util.Pair)1 SocketTimeoutException (java.net.SocketTimeoutException)1 Date (java.util.Date)1 SimpleTimeZone (java.util.SimpleTimeZone)1 TimeZone (java.util.TimeZone)1 GBDeviceEventAppInfo (nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventAppInfo)1 GBDeviceEventAppMessage (nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventAppMessage)1 GBDeviceEventCallControl (nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventCallControl)1 GBDeviceEventMusicControl (nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventMusicControl)1 GBDeviceEventNotificationControl (nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventNotificationControl)1