package cc.blynk.server.core.model.widgets; import cc.blynk.server.core.model.Pin; import cc.blynk.server.core.model.enums.PinType; import cc.blynk.server.core.model.widgets.ui.DeviceSelector; import cc.blynk.utils.JsonParser; import cc.blynk.utils.ParseUtil; import io.netty.channel.Channel; import io.netty.channel.ChannelHandlerContext; import static cc.blynk.server.core.protocol.enums.Command.APP_SYNC; import static cc.blynk.server.core.protocol.enums.Command.HARDWARE; import static cc.blynk.utils.BlynkByteBufUtil.makeUTF8StringMessage; import static cc.blynk.utils.StringUtils.BODY_SEPARATOR; import static cc.blynk.utils.StringUtils.prependDashIdAndDeviceId; /** * The Blynk Project. * Created by Dmitriy Dumanskiy. * Created on 02.12.15. */ //todo all this should be replaced with 1 Pin field. public abstract class OnePinWidget extends Widget implements AppSyncWidget, HardwareSyncWidget { public int deviceId; public PinType pinType; public byte pin = -1; public boolean pwmMode; public boolean rangeMappingOn; public int min; public int max; public volatile String value; protected static String makeHardwareBody(PinType pinType, byte pin, String value) { return "" + pinType.pintTypeChar + 'w' + BODY_SEPARATOR + pin + BODY_SEPARATOR + value; } @Override public void sendAppSync(Channel appChannel, int dashId, int targetId) { //do not send SYNC message for widgets assigned to device selector //as it will be duplicated later. if (this.deviceId >= DeviceSelector.DEVICE_SELECTOR_STARTING_ID) { return; } if (targetId == ANY_TARGET || this.deviceId == targetId) { String hardBody = makeHardwareBody(); if (hardBody != null) { String body = prependDashIdAndDeviceId(dashId, this.deviceId, hardBody); appChannel.write(makeUTF8StringMessage(APP_SYNC, SYNC_DEFAULT_MESSAGE_ID, body)); } } } public boolean isNotValid() { return pin == Pin.NO_PIN || pinType == null; } public String makeHardwareBody() { if (isNotValid() || value == null) { return null; } return isPWMSupported() ? makeHardwareBody(PinType.ANALOG, pin, value) : makeHardwareBody(pinType, pin, value); } @Override public boolean updateIfSame(int deviceId, byte pin, PinType type, String value) { if (isSame(deviceId, pin, type)) { this.value = value; return true; } return false; } @Override public void sendHardSync(ChannelHandlerContext ctx, int msgId, int deviceId) { if (this.deviceId == deviceId) { String body = makeHardwareBody(); if (body != null) { ctx.write(makeUTF8StringMessage(HARDWARE, msgId, body), ctx.voidPromise()); } } } //todo cover with test public boolean isSame(int deviceId, byte pin, PinType type) { return this.deviceId == deviceId && this.pin == pin && ( (type == this.pinType) || (this.isPWMSupported() && type == PinType.ANALOG) || (type == PinType.DIGITAL && this.pinType == PinType.ANALOG) ); } @Override public String getValue(byte pin, PinType type) { return value; } @Override public boolean hasValue(String searchValue) { return searchValue.equals(value); } @Override public String getJsonValue() { if (value == null) { return "[]"; } return JsonParser.valueToJsonAsString(value); } @Override public void append(StringBuilder sb, int deviceId) { if (this.deviceId == deviceId) { append(sb, pin, pinType, getModeType()); } } public boolean isPWMSupported() { return false; } @Override public void setProperty(String property, String propertyValue) { switch (property) { case "min" : this.min = ParseUtil.parseInt(propertyValue); break; case "max" : this.max = ParseUtil.parseInt(propertyValue); break; default: super.setProperty(property, propertyValue); break; } } }