/* Copyright (C) 2023-2024 José Rebelo This file is part of Gadgetbridge. Gadgetbridge is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Gadgetbridge is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ package nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.services; import org.apache.commons.lang3.ArrayUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventMusicControl; import nodomain.freeyourgadget.gadgetbridge.model.MusicSpec; import nodomain.freeyourgadget.gadgetbridge.model.MusicStateSpec; import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsSupport; import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.HuamiSupport; import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.AbstractZeppOsService; public class ZeppOsMusicService extends AbstractZeppOsService { private static final Logger LOG = LoggerFactory.getLogger(ZeppOsMusicService.class); private static final short ENDPOINT = 0x001b; private static final byte CMD_MEDIA_INFO = 0x03; private static final byte CMD_APP_STATE = 0x04; private static final byte CMD_BUTTON_PRESS = 0x05; private static final byte MUSIC_APP_OPEN = 0x01; private static final byte MUSIC_APP_CLOSE = 0x02; private static final byte BUTTON_PLAY = 0x00; private static final byte BUTTON_PAUSE = 0x01; private static final byte BUTTON_NEXT = 0x03; private static final byte BUTTON_PREVIOUS = 0x04; private static final byte BUTTON_VOLUME_UP = 0x05; private static final byte BUTTON_VOLUME_DOWN = 0x06; public ZeppOsMusicService(final ZeppOsSupport support) { super(support, false); } @Override public short getEndpoint() { return ENDPOINT; } @Override public void handlePayload(final byte[] payload) { switch (payload[0]) { case CMD_APP_STATE: switch (payload[1]) { case MUSIC_APP_OPEN: onMusicAppOpen(); break; case MUSIC_APP_CLOSE: onMusicAppClosed(); break; default: LOG.warn("Unexpected music app state {}", String.format("0x%02x", payload[1])); break; } return; case CMD_BUTTON_PRESS: LOG.info("Got music button press"); final GBDeviceEventMusicControl deviceEventMusicControl = new GBDeviceEventMusicControl(); switch (payload[1]) { case BUTTON_PLAY: deviceEventMusicControl.event = GBDeviceEventMusicControl.Event.PLAY; break; case BUTTON_PAUSE: deviceEventMusicControl.event = GBDeviceEventMusicControl.Event.PAUSE; break; case BUTTON_NEXT: deviceEventMusicControl.event = GBDeviceEventMusicControl.Event.NEXT; break; case BUTTON_PREVIOUS: deviceEventMusicControl.event = GBDeviceEventMusicControl.Event.PREVIOUS; break; case BUTTON_VOLUME_UP: deviceEventMusicControl.event = GBDeviceEventMusicControl.Event.VOLUMEUP; break; case BUTTON_VOLUME_DOWN: deviceEventMusicControl.event = GBDeviceEventMusicControl.Event.VOLUMEDOWN; break; default: LOG.warn("Unexpected music button {}", String.format("0x%02x", payload[1])); return; } evaluateGBDeviceEvent(deviceEventMusicControl); return; default: LOG.warn("Unexpected music byte {}", String.format("0x%02x", payload[0])); } } private void onMusicAppOpen() { getSupport().onMusicAppOpen(); } private void onMusicAppClosed() { getSupport().onMusicAppClosed(); } public void sendMusicState(final MusicSpec musicSpec, final MusicStateSpec musicStateSpec) { LOG.info("Sending music: {}, {}", musicSpec, musicStateSpec); // TODO: Encode not playing state (flag 0x20, single 0x01 byte before volume) final byte[] cmd = ArrayUtils.addAll( new byte[]{CMD_MEDIA_INFO}, HuamiSupport.encodeMusicState(getContext(), musicSpec, musicStateSpec, false) ); write("send music state", cmd); } public void sendVolume(final float volume) { LOG.info("Sending volume: {}", volume); final byte[] cmd = ArrayUtils.addAll( new byte[]{CMD_MEDIA_INFO}, HuamiSupport.encodeMusicState(getContext(), null, null, true) ); write("send volume", cmd); } }