[MercedesMe] Switch to Mercedes App SDK (#15628)
* add protocol buffer definitions * oauth rework * websocket introduction Signed-off-by: Bernd Weymann <bernd.weymann@gmail.com> Signed-off-by: Ciprian Pascu <contact@ciprianpascu.ro>
Before Width: | Height: | Size: 16 KiB |
After Width: | Height: | Size: 41 KiB |
Before Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 85 KiB |
Before Width: | Height: | Size: 235 KiB |
Before Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 32 KiB |
BIN
bundles/org.openhab.binding.mercedesme/doc/OH-Step0.png
Normal file
After Width: | Height: | Size: 32 KiB |
BIN
bundles/org.openhab.binding.mercedesme/doc/OH-Step1.png
Normal file
After Width: | Height: | Size: 43 KiB |
BIN
bundles/org.openhab.binding.mercedesme/doc/OH-Step2.png
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
bundles/org.openhab.binding.mercedesme/doc/OH-Step3.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
bundles/org.openhab.binding.mercedesme/doc/OH-capabilities.png
Normal file
After Width: | Height: | Size: 64 KiB |
@ -10,6 +10,28 @@
|
||||
<version>4.2.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>build-helper-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>add-source</goal>
|
||||
</goals>
|
||||
<phase>generate-sources</phase>
|
||||
<configuration>
|
||||
<sources>
|
||||
<source>src/3rdparty/java</source>
|
||||
</sources>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<!-- version needs to match with other projects like org.openhab.io.openhabcloud.pom.xml -->
|
||||
<dependency>
|
||||
@ -18,6 +40,13 @@
|
||||
<version>20231013</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/com.google.protobuf/protobuf-java -->
|
||||
<dependency>
|
||||
<groupId>com.google.protobuf</groupId>
|
||||
<artifactId>protobuf-java</artifactId>
|
||||
<version>4.26.1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<artifactId>org.openhab.binding.mercedesme</artifactId>
|
||||
|
7
bundles/org.openhab.binding.mercedesme/proto/README.md
Normal file
@ -0,0 +1,7 @@
|
||||
# How to protoc
|
||||
|
||||
- Check [mvn repository](https://mvnrepository.com/artifact/com.google.protobuf/protobuf-java-util) which version to use
|
||||
- Download correct protoc compiler from [maven central](https://repo1.maven.org/maven2/com/google/protobuf/protoc/) into `PROTOC_DIR`
|
||||
- Call in mercedesme binding directory `PROTOC_DIR\protoc -I=proto --java_out=gen proto/*.proto`
|
||||
- Move generated sources including subdirs from `gen` to `3rdparty\java`
|
||||
- Adapt `pom.xml` with version of step 1
|
420
bundles/org.openhab.binding.mercedesme/proto/acp.proto
Normal file
@ -0,0 +1,420 @@
|
||||
syntax = "proto3";
|
||||
package proto;
|
||||
|
||||
//import "github.com/gogo/protobuf/gogoproto/gogo.proto";
|
||||
import "gogo.proto";
|
||||
|
||||
|
||||
option (gogoproto.goproto_enum_prefix_all) = true;
|
||||
option java_package = "com.daimler.mbcarkit.proto";
|
||||
|
||||
message VVA {
|
||||
enum CommandState {
|
||||
UNKNOWN_COMMAND_STATE = 0;
|
||||
CREATED = 1010;
|
||||
ENQUEUED = 1016;
|
||||
PROCESSING = 1012;
|
||||
SUSPENDED = 1017;
|
||||
FINISHED = 1018;
|
||||
}
|
||||
|
||||
enum CommandCondition {
|
||||
UNKNWON_COMMAND_CONDITION = 0;
|
||||
NONE = 1000;
|
||||
ACCEPTED = 1001;
|
||||
REJECTED = 1002;
|
||||
TERMINATE = 1003;
|
||||
SUCCESS = 1011;
|
||||
FAILED = 1013;
|
||||
OVERWRITTEN = 1014;
|
||||
TIMEOUT = 1015;
|
||||
}
|
||||
}
|
||||
|
||||
message VehicleAPI {
|
||||
enum CommandState {
|
||||
UNKNOWN_COMMAND_STATE = 0;
|
||||
// Command execution request is accepted and an asynchronous process is
|
||||
// being initialized.
|
||||
INITIATION = 1;
|
||||
// Another process for the same vehicle and queue is active, the request has
|
||||
// been queued for later execution.
|
||||
ENQUEUED = 2;
|
||||
// The process is currently being processed by the backend.
|
||||
PROCESSING = 3;
|
||||
// The backend currently waits for the vehicle to respond to the request.
|
||||
WAITING = 4;
|
||||
// The process has finished successfully.
|
||||
FINISHED = 5;
|
||||
// There was an error while executing the command process.
|
||||
FAILED = 6;
|
||||
}
|
||||
|
||||
enum AttributeStatus {
|
||||
// Value is set and valid
|
||||
VALUE_SET = 0;
|
||||
// Value has not yet been retrieved from vehicle (but sensor etc. should be available)
|
||||
VALUE_NOT_SET = 1;
|
||||
// Value has been retrieved from vehicle but is invalid (marked as invalid by DaiVB backend)
|
||||
INVALID = 3;
|
||||
// Vehicle does not support this attribute (e.g. does not have the sensor etc.)
|
||||
NOT_AVAILABLE = 4;
|
||||
}
|
||||
|
||||
enum QueueType {
|
||||
|
||||
// the JSON enum values are lowercase, but lowercase values are not exported in golang, so
|
||||
// we allow aliasing all values.
|
||||
option allow_alias = true;
|
||||
|
||||
UNKNOWNCOMMANDQUEUETYPE = 0;
|
||||
DOORS = 10;
|
||||
AUXHEAT = 11;
|
||||
PRECOND = 12;
|
||||
CHARGEOPT = 13;
|
||||
MAINTENANCE = 14;
|
||||
TCU = 15;
|
||||
FEED = 16;
|
||||
SERVICEACTIVATION = 17;
|
||||
ATP = 18;
|
||||
ASSISTANCE = 19;
|
||||
RACP = 20;
|
||||
WEEKPROFILE = 21;
|
||||
REMOTEDIAGNOSIS = 22;
|
||||
FLSH = 23; //(ALSO USED BY SIGPOS/RVF)
|
||||
TEMPERATURE = 24;
|
||||
TRIPCOMP = 25;
|
||||
ENGINE = 26;
|
||||
THEFTALARM = 27;
|
||||
WINDOW = 28;
|
||||
HEADUNIT = 29;
|
||||
MECALL = 31;
|
||||
IMMOBILIZER = 32;
|
||||
RENTALSIGNAL = 33;
|
||||
BCF = 34; //(BLACKCHANNEL)
|
||||
PLUGANDCHARGE = 35;
|
||||
CARSHARINGMODULE = 36;
|
||||
BATTERY = 37;
|
||||
ONBOARDFENCES = 38;
|
||||
SPEEDFENCES = 39;
|
||||
CHARGINGTARIFFS = 40;
|
||||
RTMCONFIG = 41;
|
||||
MAINTENANCECOMPUTER = 42;
|
||||
MECALL2 = 43;
|
||||
AUTOMATEDVALETPARKING = 44;
|
||||
CHARGECONTROL = 45;
|
||||
SPEEDALERT = 46;
|
||||
|
||||
unknowncommandqueuetype = 0;
|
||||
doors = 10;
|
||||
auxheat = 11;
|
||||
precond = 12;
|
||||
chargeopt = 13;
|
||||
maintenance = 14;
|
||||
tcu = 15;
|
||||
feed = 16;
|
||||
serviceactivation = 17;
|
||||
atp = 18;
|
||||
assistance = 19;
|
||||
racp = 20;
|
||||
weekprofile = 21;
|
||||
remotediagnosis = 22;
|
||||
flsh = 23; //(also used by sigpos/RVF)
|
||||
temperature = 24;
|
||||
tripcomp = 25;
|
||||
engine = 26;
|
||||
theftalarm = 27;
|
||||
window = 28;
|
||||
headunit = 29;
|
||||
mecall = 31;
|
||||
immobilizer = 32;
|
||||
rentalsignal = 33;
|
||||
bcf = 34; //(blackchannel)
|
||||
plugandcharge = 35;
|
||||
carsharingmodule = 36;
|
||||
battery = 37;
|
||||
onboardfences = 38;
|
||||
speedfences = 39;
|
||||
chargingtariffs = 40;
|
||||
rtmconfig = 41;
|
||||
maintenancecomputer = 42;
|
||||
mecall2 = 43;
|
||||
automatedvaletparking = 44;
|
||||
chargecontrol = 45;
|
||||
speedalert = 46;
|
||||
}
|
||||
}
|
||||
|
||||
message ACP {
|
||||
|
||||
enum CommandType {
|
||||
|
||||
// the JSON enum values are lowercase, but lowercase values are not exported in golang, so
|
||||
// we allow aliasing all values.
|
||||
option allow_alias = true;
|
||||
|
||||
UNKNOWNCOMMANDTYPE = 0;
|
||||
DOORSLOCK = 100;
|
||||
DOORSUNLOCK = 110;
|
||||
TRUNKUNLOCK = 115;
|
||||
FUELFLAPUNLOCK = 116;
|
||||
CHARGEFLAPUNLOCK = 117;
|
||||
CHARGECOUPLERUNLOCK = 118;
|
||||
DOORSPREPARERENTAL = 120;
|
||||
DOORSSECUREVEHICLE = 130;
|
||||
AUXHEATSTART = 300;
|
||||
AUXHEATSTOP = 310;
|
||||
AUXHEATCONFIGURE = 320;
|
||||
TEMPERATURECONFIGURE = 350;
|
||||
WEEKPROFILECONFIGURE = 360;
|
||||
WEEKPROFILEV2CONFIGURE = 370;
|
||||
PRECONDSTART = 400;
|
||||
PRECONDSTOP = 410;
|
||||
PRECONDCONFIGURE = 420;
|
||||
PRECONDCONFIGURESEATS = 425;
|
||||
CHARGEOPTCONFIGURE = 430;
|
||||
CHARGEOPTSTART = 440;
|
||||
CHARGEOPTSTOP = 450;
|
||||
FEEDPOI = 500;
|
||||
FEEDFREETEXT = 510;
|
||||
ENGINESTART = 550;
|
||||
ENGINESTOP = 560;
|
||||
ENGINEAVPSTART = 570;
|
||||
TCUWAKEUP = 600;
|
||||
TCUSWUPDATE = 610;
|
||||
TCURCSRESET = 620;
|
||||
TCUINTERROGATION = 630;
|
||||
SPEEDALERTSTART = 710;
|
||||
SPEEDALERTSTOP = 720;
|
||||
FLSHSTART = 750; // (DEPRECATED)
|
||||
FLSHSTOP = 760; // (DEPRECATED)
|
||||
SIGPOSSTART = 770;
|
||||
CONTRACTCONFIGURE = 800;
|
||||
CONTRACTREMOVE = 810;
|
||||
ROOTCONFIGURE = 820;
|
||||
ROOTREMOVE = 830;
|
||||
TRIPCOMP = 850; // RESET TRIPCOMP
|
||||
MAINTENANCECONFIGURE = 930;
|
||||
MAINTENANCECOMPUTEROFFSET = 931;
|
||||
SHORTTESTEXECUTE = 935;
|
||||
SERVICEACTIVATIONCONFIGURE = 940;
|
||||
DC2SERVICEACTIVATIONCONFIGURE = 945;
|
||||
DC2RAWDOWNLOAD = 950; //(TEST COMMAND)
|
||||
APPLICATIONCONFIGURATION = 955; // (DC2+)
|
||||
DC2STARTTRACKING = 960; // (TEST COMMAND)
|
||||
ATPSEQUENCE = 990;
|
||||
THEFTALARMTOGGLEINTERIOR = 1000;
|
||||
THEFTALARMTOGGLETOW = 1010;
|
||||
THEFTALARMSELECTINTERIORTOW = 1020;
|
||||
THEFTALARMDESELECTINTERIORTOW = 1030;
|
||||
THEFTALARMSTOP = 1040;
|
||||
WINDOWOPEN = 1100;
|
||||
WINDOWCLOSE = 1110;
|
||||
WINDOWVENTILATE = 1120;
|
||||
WINDOWMOVE = 1121;
|
||||
ROOFOPEN = 1130;
|
||||
ROOFCLOSE = 1140;
|
||||
ROOFLIFT = 1150;
|
||||
ROOFMOVE = 1151;
|
||||
BATTERYMAXSOC = 2000;
|
||||
BATTERYCHARGEPROGRAM = 2010;
|
||||
CHARGEPROGRAMCONFIGURE = 2020;
|
||||
ONBOARDFENCESCREATE = 2100;
|
||||
ONBOARDFENCESUPDATE = 2110;
|
||||
ONBOARDFENCESDELETE = 2120;
|
||||
SPEEDFENCESCREATE = 2200;
|
||||
SPEEDFENCESUPDATE = 2210;
|
||||
SPEEDFENCESDELETE = 2220;
|
||||
CHARGINGTARIFFSCREATE = 2300;
|
||||
CHARGINGTARIFFSUPDATE = 2310;
|
||||
CHARGINGTARIFFSDELETE = 2320;
|
||||
THEFTALARMSTART = 2500;
|
||||
THEFTALARMSELECTINTERIOR = 2510;
|
||||
THEFTALARMDESELECTINTERIOR = 2520;
|
||||
THEFTALARMSELECTTOW = 2530;
|
||||
THEFTALARMDESELECTTOW = 2540;
|
||||
THEFTALARMSELECTDAMAGEDETECTION = 2550;
|
||||
THEFTALARMDESELECTDAMAGEDETECTION = 2560;
|
||||
THEFTALARMCONFIRMDAMAGEDETECTION = 2570;
|
||||
MECALL2START = 2600;
|
||||
UDXTRIGGERSYNCHRONIZATION = 1200;
|
||||
UDXACTIVEUSERPROFILE = 1210;
|
||||
UDXRESETUSERDATA = 1220;
|
||||
USERPROFSYNCH = 1230;
|
||||
USERDATARESET = 1240;
|
||||
PROFACTIVATIONSNAP = 1250;
|
||||
PROFACTIVATIONDIRECT = 1255;
|
||||
SOFTWAREUPDATE = 1260;
|
||||
PUSHNOTIFICATION = 1270;
|
||||
MECALLCOMMAND = 1310;
|
||||
PRECONDSTARTRCS = 1400;
|
||||
PRECONDSTOPRCS = 1410;
|
||||
PRECONDCONFIGURERCS = 1420;
|
||||
TCUCONFIGURE = 1430;
|
||||
EDISONSERVICEACTIVATION = 1431;
|
||||
TESTSEQUENCE = 1432;
|
||||
PRECONDCONFIGURERACP = 1433;
|
||||
CHARGEOPTCONFIGURERACP = 1434;
|
||||
TARIFFTABLEDOWNLOAD = 1435;
|
||||
PRECONDSTARTRACP = 1436;
|
||||
PRECONDSTOPRACP = 1437;
|
||||
ROOTCERTIFICATEREMOVE = 1438;
|
||||
ONREQUESTPROBEUPLOAD = 1439;
|
||||
ROOTCERTIFICATEDOWNLOAD = 1440;
|
||||
CONTRACTCERTIFICATEREMOVE = 1441;
|
||||
CONTRACTCERTIFICATEDOWNLOAD = 1442;
|
||||
PROBECONFIGURATIONUPDATE = 1443;
|
||||
RDIAGDELETEECU = 1500;
|
||||
RDIAGSTATUSREPORT = 1501;
|
||||
RDIAGEXECUTION = 1502;
|
||||
IMMOBILIZERCHALLENGE = 1600;
|
||||
IMMOBILIZERSEARCHKEYLINE = 1610;
|
||||
IMMOBILIZERRELEASEKEYLINE = 1620;
|
||||
IMMOBILIZERLOCKKEYLINE = 1630;
|
||||
IMMOBILIZERLOCKVEHICLE = 1631;
|
||||
IMMOBILIZERRELEASEVEHICLE = 1621;
|
||||
SETRENTALSIGNAL = 1700;
|
||||
BLACKCHANNELDOWNLOAD = 1800;
|
||||
BLACKCHANNELUPLOAD = 1810;
|
||||
CONFIGURECSM = 1900;
|
||||
UPDATEVEHICLEINFO = 1901;
|
||||
RELAYMESSAGETOCSM = 1902;
|
||||
RELAYRENTALREQUESTTOCSB = 1903;
|
||||
RTMDOWNLOADCONFIG = 2400;
|
||||
RTMREADCONFIG = 2410;
|
||||
AVPACTIVATE = 2700;
|
||||
CHARGECONTROLCONFIGURE = 2800;
|
||||
|
||||
unknownCommandType = 0;
|
||||
doorsLock = 100;
|
||||
doorsUnlock = 110;
|
||||
trunkUnlock = 115;
|
||||
fuelflapUnlock = 116;
|
||||
chargeflapUnlock = 117;
|
||||
chargecouplerUnlock = 118;
|
||||
doorsPrepareRental = 120;
|
||||
doorsSecureVehicle = 130;
|
||||
auxheatStart = 300;
|
||||
auxheatStop = 310;
|
||||
auxheatConfigure = 320;
|
||||
temperatureConfigure = 350;
|
||||
weekprofileConfigure = 360;
|
||||
weekprofileV2Configure = 370;
|
||||
precondStart = 400;
|
||||
precondStop = 410;
|
||||
precondConfigure = 420;
|
||||
precondConfigureSeats = 425;
|
||||
chargeoptConfigure = 430;
|
||||
chargeoptStart = 440;
|
||||
chargeoptStop = 450;
|
||||
feedPoi = 500;
|
||||
feedFreetext = 510;
|
||||
engineStart = 550;
|
||||
engineStop = 560;
|
||||
engineAvpstart = 570;
|
||||
tcuWakeup = 600;
|
||||
tcuSwUpdate = 610;
|
||||
tcuRcsReset = 620;
|
||||
tcuInterrogation = 630;
|
||||
speedalertStart = 710;
|
||||
speedalertStop = 720;
|
||||
flshStart = 750; // (DEPRECATED)
|
||||
flshStop = 760; // (DEPRECATED)
|
||||
sigposStart = 770;
|
||||
contractConfigure = 800;
|
||||
contractRemove = 810;
|
||||
rootConfigure = 820;
|
||||
rootRemove = 830;
|
||||
tripcomp = 850; // reset tripcomp
|
||||
maintenanceConfigure = 930;
|
||||
maintenanceComputerOffset = 931;
|
||||
shorttestExecute = 935;
|
||||
serviceactivationConfigure = 940;
|
||||
dc2ServiceactivationConfigure = 945;
|
||||
dc2RawDownload = 950; //(test command)
|
||||
applicationConfiguration = 955; // (DC2+)
|
||||
dc2StartTracking = 960; // (test command)
|
||||
atpSequence = 990;
|
||||
theftalarmToggleInterior = 1000;
|
||||
theftalarmToggleTow = 1010;
|
||||
theftalarmSelectInteriorTow = 1020;
|
||||
theftalarmDeselectInteriorTow = 1030;
|
||||
theftalarmStop = 1040;
|
||||
windowOpen = 1100;
|
||||
windowClose = 1110;
|
||||
windowVentilate = 1120;
|
||||
windowMove = 1121;
|
||||
roofOpen = 1130;
|
||||
roofClose = 1140;
|
||||
roofLift = 1150;
|
||||
roofMove = 1151;
|
||||
batteryMaxsoc = 2000;
|
||||
batteryChargeprogram = 2010;
|
||||
chargeprogramconfigure = 2020;
|
||||
onboardfencesCreate = 2100;
|
||||
onboardfencesUpdate = 2110;
|
||||
onboardfencesDelete = 2120;
|
||||
speedfencesCreate = 2200;
|
||||
speedfencesUpdate = 2210;
|
||||
speedfencesDelete = 2220;
|
||||
chargingtariffsCreate = 2300;
|
||||
chargingtariffsUpdate = 2310;
|
||||
chargingtariffsDelete = 2320;
|
||||
theftalarmstart = 2500;
|
||||
theftalarmselectinterior = 2510;
|
||||
theftalarmdeselectinterior = 2520;
|
||||
theftalarmselecttow = 2530;
|
||||
theftalarmdeselecttow = 2540;
|
||||
theftalarmselectdamagedetection = 2550;
|
||||
theftalarmdeselectdamagedetection = 2560;
|
||||
theftalarmconfirmdamagedetection = 2570;
|
||||
mecall2start = 2600;
|
||||
udxTriggerSynchronization = 1200;
|
||||
udxActiveUserProfile = 1210;
|
||||
udxResetUserData = 1220;
|
||||
userProfSynch = 1230;
|
||||
userDataReset = 1240;
|
||||
profActivationSnap = 1250;
|
||||
profActivationDirect = 1255;
|
||||
softwareUpdate = 1260;
|
||||
pushNotification = 1270;
|
||||
mecallcommand = 1310;
|
||||
precondStartRcs = 1400;
|
||||
precondStopRcs = 1410;
|
||||
precondConfigureRcs = 1420;
|
||||
tcuConfigure = 1430;
|
||||
edisonServiceActivation = 1431;
|
||||
testSequence = 1432;
|
||||
precondConfigureRacp = 1433;
|
||||
chargeoptConfigureRacp = 1434;
|
||||
tariffTableDownload = 1435;
|
||||
precondStartRacp = 1436;
|
||||
precondStopRacp = 1437;
|
||||
rootCertificateRemove = 1438;
|
||||
onRequestProbeUpload = 1439;
|
||||
rootCertificateDownload = 1440;
|
||||
contractCertificateRemove = 1441;
|
||||
contractCertificateDownload = 1442;
|
||||
probeConfigurationUpdate = 1443;
|
||||
rdiagDeleteEcu = 1500;
|
||||
rdiagStatusReport = 1501;
|
||||
rdiagExecution = 1502;
|
||||
immobilizerChallenge = 1600;
|
||||
immobilizerSearchKeyline = 1610;
|
||||
immobilizerReleaseKeyline = 1620;
|
||||
immobilizerLockKeyline = 1630;
|
||||
immobilizerLockVehicle = 1631;
|
||||
immobilizerReleaseVehicle = 1621;
|
||||
setRentalSignal = 1700;
|
||||
blackchannelDownload = 1800;
|
||||
blackchannelUpload = 1810;
|
||||
configurecsm = 1900;
|
||||
updatevehicleinfo = 1901;
|
||||
relaymessagetocsm = 1902;
|
||||
relayrentalrequesttocsb = 1903;
|
||||
rtmDownloadConfig = 2400;
|
||||
rtmReadConfig = 2410;
|
||||
avpActivate = 2700;
|
||||
chargecontrolconfigure = 2800;
|
||||
}
|
||||
}
|
46
bundles/org.openhab.binding.mercedesme/proto/client.proto
Normal file
@ -0,0 +1,46 @@
|
||||
syntax = "proto3";
|
||||
package proto;
|
||||
|
||||
import "protos.proto";
|
||||
import "service-activation.proto";
|
||||
import "user-events.proto";
|
||||
import "vehicle-commands.proto";
|
||||
import "vehicle-events.proto";
|
||||
import "vehicleapi.proto";
|
||||
|
||||
option java_package = "com.daimler.mbcarkit.proto";
|
||||
|
||||
// message that is sent from the client
|
||||
// Sending direction: App -> Websocket (-> AppTwin)
|
||||
message ClientMessage {
|
||||
reserved 8;
|
||||
string tracking_id = 5;
|
||||
oneof msg {
|
||||
UnsubscribeRequest unsubscribeRequest = 2;
|
||||
CommandRequest commandRequest = 3;
|
||||
TrackingEvent tracking_event = 4;
|
||||
ConfigurePingInterval ping_interval = 6;
|
||||
AcknowledgeVEPRequest acknowledge_vep_request = 7;
|
||||
AcknowledgeServiceStatusUpdatesByVIN acknowledge_service_status_updates_by_vin = 9;
|
||||
AcknowledgeServiceStatusUpdate acknowledge_service_status_update = 13;
|
||||
AcknowledgeUserDataUpdate acknowledge_user_data_update = 10;
|
||||
AcknowledgeUserPictureUpdate acknowledge_user_picture_update = 11;
|
||||
AcknowledgeUserPINUpdate acknowledge_user_pin_update = 12;
|
||||
UpdateUserJWTRequest update_user_jwt_request = 14;
|
||||
AcknowledgeUserVehicleAuthChangedUpdate acknowledge_user_vehicle_auth_changed_update = 15;
|
||||
AcknowledgeAbilityToGetVehicleMasterDataFromRestAPI acknowledge_ability_to_get_vehicle_master_data_from_rest_api = 16;
|
||||
AcknowledgeVehicleUpdated acknowledge_vehicle_updated = 17;
|
||||
AcknowledgePreferredDealerChange acknowledge_preferred_dealer_change = 18;
|
||||
AcknowledgeAppTwinCommandStatusUpdatesByVIN acknowledge_apptwin_command_status_update_by_vin = 19;
|
||||
Logout logout = 20;
|
||||
AppTwinPendingCommandsResponse apptwin_pending_commands_response = 21;
|
||||
AcknowledgeVEPUpdatesByVIN acknowledge_vep_updates_by_vin = 22;
|
||||
AcknowledgeAssignedVehicles acknowledge_assigned_vehicles = 23;
|
||||
}
|
||||
}
|
||||
|
||||
// Message to send from the app right before logging out of keycloak
|
||||
// Stops the corresponding AppTwin actor and shuts it down and
|
||||
// stops the websocket actor (but does not shut it down. This automatically happens, when the websocket connection is terminated)
|
||||
message Logout {
|
||||
}
|
15
bundles/org.openhab.binding.mercedesme/proto/cluster.proto
Normal file
@ -0,0 +1,15 @@
|
||||
syntax = "proto3";
|
||||
package proto;
|
||||
|
||||
option java_package = "com.daimler.mbcarkit.proto";
|
||||
|
||||
enum MemberStatus {
|
||||
UNKNOWN_MEMBER_STATUS = 0;
|
||||
STARTING = 1;
|
||||
READY = 2;
|
||||
STOPPING = 3;
|
||||
}
|
||||
message AppTwinMemberStatusValue {
|
||||
MemberStatus status = 1;
|
||||
uint32 apptwin_count = 2;
|
||||
}
|
22
bundles/org.openhab.binding.mercedesme/proto/eventpush.proto
Normal file
@ -0,0 +1,22 @@
|
||||
syntax = "proto3";
|
||||
package proto;
|
||||
import "acp.proto";
|
||||
|
||||
//import "github.com/gogo/protobuf/gogoproto/gogo.proto";
|
||||
import "gogo.proto";
|
||||
|
||||
option (gogoproto.goproto_enum_prefix_all) = true;
|
||||
option java_package = "com.daimler.mbcarkit.proto";
|
||||
|
||||
message EventPushCommand {
|
||||
string vin = 1 [json_name = "vin"];
|
||||
VVA.CommandState state = 2 [json_name = "acpState"];
|
||||
VVA.CommandCondition condition = 3 [json_name = "acpCondition"];
|
||||
ACP.CommandType type = 4 [json_name = "acpCommandType"];
|
||||
int64 process_id = 5 [json_name = "pid"];
|
||||
string tracking_id = 6 [json_name = "trackingId"];
|
||||
string correlation_id = 7 [json_name = "correlationId"];
|
||||
repeated int32 error_codes = 8 [json_name = "errorCodes"];
|
||||
string guid = 9 [json_name = "guid"];
|
||||
int64 timestamp_in_s = 10 [ json_name = "timestamp" ];
|
||||
}
|
144
bundles/org.openhab.binding.mercedesme/proto/gogo.proto
Normal file
@ -0,0 +1,144 @@
|
||||
// Protocol Buffers for Go with Gadgets
|
||||
//
|
||||
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
|
||||
// http://github.com/gogo/protobuf
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
syntax = "proto2";
|
||||
package gogoproto;
|
||||
|
||||
import "google/protobuf/descriptor.proto";
|
||||
|
||||
option java_package = "com.google.protobuf";
|
||||
option java_outer_classname = "GoGoProtos";
|
||||
option go_package = "github.com/gogo/protobuf/gogoproto";
|
||||
|
||||
extend google.protobuf.EnumOptions {
|
||||
optional bool goproto_enum_prefix = 62001;
|
||||
optional bool goproto_enum_stringer = 62021;
|
||||
optional bool enum_stringer = 62022;
|
||||
optional string enum_customname = 62023;
|
||||
optional bool enumdecl = 62024;
|
||||
}
|
||||
|
||||
extend google.protobuf.EnumValueOptions {
|
||||
optional string enumvalue_customname = 66001;
|
||||
}
|
||||
|
||||
extend google.protobuf.FileOptions {
|
||||
optional bool goproto_getters_all = 63001;
|
||||
optional bool goproto_enum_prefix_all = 63002;
|
||||
optional bool goproto_stringer_all = 63003;
|
||||
optional bool verbose_equal_all = 63004;
|
||||
optional bool face_all = 63005;
|
||||
optional bool gostring_all = 63006;
|
||||
optional bool populate_all = 63007;
|
||||
optional bool stringer_all = 63008;
|
||||
optional bool onlyone_all = 63009;
|
||||
|
||||
optional bool equal_all = 63013;
|
||||
optional bool description_all = 63014;
|
||||
optional bool testgen_all = 63015;
|
||||
optional bool benchgen_all = 63016;
|
||||
optional bool marshaler_all = 63017;
|
||||
optional bool unmarshaler_all = 63018;
|
||||
optional bool stable_marshaler_all = 63019;
|
||||
|
||||
optional bool sizer_all = 63020;
|
||||
|
||||
optional bool goproto_enum_stringer_all = 63021;
|
||||
optional bool enum_stringer_all = 63022;
|
||||
|
||||
optional bool unsafe_marshaler_all = 63023;
|
||||
optional bool unsafe_unmarshaler_all = 63024;
|
||||
|
||||
optional bool goproto_extensions_map_all = 63025;
|
||||
optional bool goproto_unrecognized_all = 63026;
|
||||
optional bool gogoproto_import = 63027;
|
||||
optional bool protosizer_all = 63028;
|
||||
optional bool compare_all = 63029;
|
||||
optional bool typedecl_all = 63030;
|
||||
optional bool enumdecl_all = 63031;
|
||||
|
||||
optional bool goproto_registration = 63032;
|
||||
optional bool messagename_all = 63033;
|
||||
|
||||
optional bool goproto_sizecache_all = 63034;
|
||||
optional bool goproto_unkeyed_all = 63035;
|
||||
}
|
||||
|
||||
extend google.protobuf.MessageOptions {
|
||||
optional bool goproto_getters = 64001;
|
||||
optional bool goproto_stringer = 64003;
|
||||
optional bool verbose_equal = 64004;
|
||||
optional bool face = 64005;
|
||||
optional bool gostring = 64006;
|
||||
optional bool populate = 64007;
|
||||
optional bool stringer = 67008;
|
||||
optional bool onlyone = 64009;
|
||||
|
||||
optional bool equal = 64013;
|
||||
optional bool description = 64014;
|
||||
optional bool testgen = 64015;
|
||||
optional bool benchgen = 64016;
|
||||
optional bool marshaler = 64017;
|
||||
optional bool unmarshaler = 64018;
|
||||
optional bool stable_marshaler = 64019;
|
||||
|
||||
optional bool sizer = 64020;
|
||||
|
||||
optional bool unsafe_marshaler = 64023;
|
||||
optional bool unsafe_unmarshaler = 64024;
|
||||
|
||||
optional bool goproto_extensions_map = 64025;
|
||||
optional bool goproto_unrecognized = 64026;
|
||||
|
||||
optional bool protosizer = 64028;
|
||||
optional bool compare = 64029;
|
||||
|
||||
optional bool typedecl = 64030;
|
||||
|
||||
optional bool messagename = 64033;
|
||||
|
||||
optional bool goproto_sizecache = 64034;
|
||||
optional bool goproto_unkeyed = 64035;
|
||||
}
|
||||
|
||||
extend google.protobuf.FieldOptions {
|
||||
optional bool nullable = 65001;
|
||||
optional bool embed = 65002;
|
||||
optional string customtype = 65003;
|
||||
optional string customname = 65004;
|
||||
optional string jsontag = 65005;
|
||||
optional string moretags = 65006;
|
||||
optional string casttype = 65007;
|
||||
optional string castkey = 65008;
|
||||
optional string castvalue = 65009;
|
||||
|
||||
optional bool stdtime = 65010;
|
||||
optional bool stdduration = 65011;
|
||||
optional bool wktpointer = 65012;
|
||||
|
||||
}
|
@ -0,0 +1,95 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package google.protobuf;
|
||||
|
||||
option cc_enable_arenas = true;
|
||||
option go_package = "google.golang.org/protobuf/types/known/structpb";
|
||||
option java_package = "com.google.protobuf";
|
||||
option java_outer_classname = "StructProto";
|
||||
option java_multiple_files = true;
|
||||
option objc_class_prefix = "GPB";
|
||||
option csharp_namespace = "Google.Protobuf.WellKnownTypes";
|
||||
|
||||
// `Struct` represents a structured data value, consisting of fields
|
||||
// which map to dynamically typed values. In some languages, `Struct`
|
||||
// might be supported by a native representation. For example, in
|
||||
// scripting languages like JS a struct is represented as an
|
||||
// object. The details of that representation are described together
|
||||
// with the proto support for the language.
|
||||
//
|
||||
// The JSON representation for `Struct` is JSON object.
|
||||
message Struct {
|
||||
// Unordered map of dynamically typed values.
|
||||
map<string, Value> fields = 1;
|
||||
}
|
||||
|
||||
// `Value` represents a dynamically typed value which can be either
|
||||
// null, a number, a string, a boolean, a recursive struct value, or a
|
||||
// list of values. A producer of value is expected to set one of these
|
||||
// variants. Absence of any variant indicates an error.
|
||||
//
|
||||
// The JSON representation for `Value` is JSON value.
|
||||
message Value {
|
||||
// The kind of value.
|
||||
oneof kind {
|
||||
// Represents a null value.
|
||||
NullValue null_value = 1;
|
||||
// Represents a double value.
|
||||
double number_value = 2;
|
||||
// Represents a string value.
|
||||
string string_value = 3;
|
||||
// Represents a boolean value.
|
||||
bool bool_value = 4;
|
||||
// Represents a structured value.
|
||||
Struct struct_value = 5;
|
||||
// Represents a repeated `Value`.
|
||||
ListValue list_value = 6;
|
||||
}
|
||||
}
|
||||
|
||||
// `NullValue` is a singleton enumeration to represent the null value for the
|
||||
// `Value` type union.
|
||||
//
|
||||
// The JSON representation for `NullValue` is JSON `null`.
|
||||
enum NullValue {
|
||||
// Null value.
|
||||
NULL_VALUE = 0;
|
||||
}
|
||||
|
||||
// `ListValue` is a wrapper around a repeated field of values.
|
||||
//
|
||||
// The JSON representation for `ListValue` is JSON array.
|
||||
message ListValue {
|
||||
// Repeated field of dynamically typed values.
|
||||
repeated Value values = 1;
|
||||
}
|
@ -0,0 +1,123 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Wrappers for primitive (non-message) types. These types are useful
|
||||
// for embedding primitives in the `google.protobuf.Any` type and for places
|
||||
// where we need to distinguish between the absence of a primitive
|
||||
// typed field and its default value.
|
||||
//
|
||||
// These wrappers have no meaningful use within repeated fields as they lack
|
||||
// the ability to detect presence on individual elements.
|
||||
// These wrappers have no meaningful use within a map or a oneof since
|
||||
// individual entries of a map or fields of a oneof can already detect presence.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package google.protobuf;
|
||||
|
||||
option cc_enable_arenas = true;
|
||||
option go_package = "google.golang.org/protobuf/types/known/wrapperspb";
|
||||
option java_package = "com.google.protobuf";
|
||||
option java_outer_classname = "WrappersProto";
|
||||
option java_multiple_files = true;
|
||||
option objc_class_prefix = "GPB";
|
||||
option csharp_namespace = "Google.Protobuf.WellKnownTypes";
|
||||
|
||||
// Wrapper message for `double`.
|
||||
//
|
||||
// The JSON representation for `DoubleValue` is JSON number.
|
||||
message DoubleValue {
|
||||
// The double value.
|
||||
double value = 1;
|
||||
}
|
||||
|
||||
// Wrapper message for `float`.
|
||||
//
|
||||
// The JSON representation for `FloatValue` is JSON number.
|
||||
message FloatValue {
|
||||
// The float value.
|
||||
float value = 1;
|
||||
}
|
||||
|
||||
// Wrapper message for `int64`.
|
||||
//
|
||||
// The JSON representation for `Int64Value` is JSON string.
|
||||
message Int64Value {
|
||||
// The int64 value.
|
||||
int64 value = 1;
|
||||
}
|
||||
|
||||
// Wrapper message for `uint64`.
|
||||
//
|
||||
// The JSON representation for `UInt64Value` is JSON string.
|
||||
message UInt64Value {
|
||||
// The uint64 value.
|
||||
uint64 value = 1;
|
||||
}
|
||||
|
||||
// Wrapper message for `int32`.
|
||||
//
|
||||
// The JSON representation for `Int32Value` is JSON number.
|
||||
message Int32Value {
|
||||
// The int32 value.
|
||||
int32 value = 1;
|
||||
}
|
||||
|
||||
// Wrapper message for `uint32`.
|
||||
//
|
||||
// The JSON representation for `UInt32Value` is JSON number.
|
||||
message UInt32Value {
|
||||
// The uint32 value.
|
||||
uint32 value = 1;
|
||||
}
|
||||
|
||||
// Wrapper message for `bool`.
|
||||
//
|
||||
// The JSON representation for `BoolValue` is JSON `true` and `false`.
|
||||
message BoolValue {
|
||||
// The bool value.
|
||||
bool value = 1;
|
||||
}
|
||||
|
||||
// Wrapper message for `string`.
|
||||
//
|
||||
// The JSON representation for `StringValue` is JSON string.
|
||||
message StringValue {
|
||||
// The string value.
|
||||
string value = 1;
|
||||
}
|
||||
|
||||
// Wrapper message for `bytes`.
|
||||
//
|
||||
// The JSON representation for `BytesValue` is JSON string.
|
||||
message BytesValue {
|
||||
// The bytes value.
|
||||
bytes value = 1;
|
||||
}
|
136
bundles/org.openhab.binding.mercedesme/proto/protos.proto
Normal file
@ -0,0 +1,136 @@
|
||||
syntax = "proto3";
|
||||
package proto;
|
||||
|
||||
option java_package = "com.daimler.mbcarkit.proto";
|
||||
|
||||
// SubscriptionRequest is sent to an actor to indicate that the sender wants to subscribe
|
||||
// to events of specific topics. By convention the "Sender" property of the actor message is the
|
||||
// Subscriber and will receive the events.
|
||||
message SubscribeRequest {
|
||||
|
||||
// An array of topics for which the Subscriber wants to be notified from the Receiver of this message
|
||||
repeated string topics = 1;
|
||||
|
||||
// indicates whether the previous set of topics should be replaced or whether the content of
|
||||
// topics should be merged into the already existing set of topics in the publisher actor. E.g. You're already
|
||||
// subscribed to topics A and B. If you send a SubscribeRequest with B and C:
|
||||
// replace = true -> you are subscribed to B and C
|
||||
// replace = false -> you are subscribed to A, B and C
|
||||
bool replace = 2;
|
||||
}
|
||||
|
||||
// SubscribeResponse is returned by the actor which received a SubscribeRequest. In case of a successful subscription
|
||||
// success will be true and error_codes empty/nil. In case of an error the errors map will contain
|
||||
// information that points to the reason for failure. The error map's keys are topics that have resulted in an error.
|
||||
// The message also contains all successfully subscribed topics under the `subscribed_topics` key.
|
||||
// By convention if an SubscribeRequest is sent for topics that have already been subscribed to, the SubscribeResponse
|
||||
// will be successful and no error will be returned.
|
||||
message SubscribeResponse {
|
||||
bool success = 1;
|
||||
map<string, SubscriptionError> errors = 2;
|
||||
repeated string subscribed_topics = 3;
|
||||
}
|
||||
|
||||
// UnsubscribeRequest is sent to an actor to indicate that the sender wants to unsubscribe
|
||||
// from events specified by the topics array.
|
||||
message UnsubscribeRequest {
|
||||
|
||||
// An array of topics for which the Subscriber does not want to receive any more messages
|
||||
repeated string topics = 1;
|
||||
|
||||
// Whether the publisher should respond
|
||||
bool anticipate_response = 2;
|
||||
}
|
||||
|
||||
// UnsubscribeResponse is returned by the actor which received a UnsubscribeRequest. In case of a successful removal,
|
||||
// success will be true and error_codes empty/nil. In case of an error the errors map will contain
|
||||
// information that points to the reason for failure. The error map's keys are topics that have resulted in an error.
|
||||
// The message also contains all successfully subscribed topics under the `unsubscribed_topics` key.
|
||||
// By convention if an UnsubscribeRequest is sent for topics that have already been unsubscribed from the UnsubscribeResponse
|
||||
// will be successful and no error will be returned.
|
||||
message UnsubscribeResponse {
|
||||
bool success = 1;
|
||||
map<string, SubscriptionError> errors = 2;
|
||||
repeated string unsubscribed_topics = 3;
|
||||
}
|
||||
|
||||
enum SubscriptionErrorType {
|
||||
UNKNOWN = 0;
|
||||
INVALID_JWT = 1;
|
||||
}
|
||||
|
||||
message SubscriptionError {
|
||||
repeated SubscriptionErrorType code = 1;
|
||||
repeated string message = 2; // Optional
|
||||
}
|
||||
|
||||
// Sent from Websocket-Service -> AppTwin
|
||||
message SubscribeToAppTwinRequest {
|
||||
string session_id = 1;
|
||||
string ciam_id = 2;
|
||||
|
||||
// additional data
|
||||
string device_locale = 3;
|
||||
string app_id = 4;
|
||||
string app_version = 5;
|
||||
OperatingSystemName os_name = 6;
|
||||
string os_version = 7;
|
||||
string device_model = 8;
|
||||
string network_carrier = 9;
|
||||
string sdk_version = 10;
|
||||
}
|
||||
|
||||
message ResubscribeToAppTwinRequest {
|
||||
string session_id = 1;
|
||||
string ciam_id = 2;
|
||||
}
|
||||
|
||||
message ResubscribeToAppTwinResponse {
|
||||
enum ResubscribeResult {
|
||||
UNKNOWN_ERROR = 0;
|
||||
SUCCESS = 1;
|
||||
INVALID_JWT_ERROR = 2;
|
||||
TARGET_DOES_NOT_EXIST = 3;
|
||||
}
|
||||
|
||||
ResubscribeResult result = 1;
|
||||
}
|
||||
|
||||
enum OperatingSystemName {
|
||||
UNKNOWN_OPERATING_SYSTEM = 0;
|
||||
IOS = 1;
|
||||
ANDROID = 2;
|
||||
INT_TEST = 3;
|
||||
MANUAL_TEST = 4;
|
||||
WEB = 5;
|
||||
}
|
||||
|
||||
// Sent from AppTwin -> Websocket-Service
|
||||
message SubscribeToAppTwinResponse {
|
||||
bool success = 1;
|
||||
SubscriptionErrorType error_code = 2;
|
||||
}
|
||||
|
||||
message UnsubscribeFromAppTwinRequest {
|
||||
string session_id = 1;
|
||||
}
|
||||
|
||||
message UnsubscribeFromAppTwinResponse {
|
||||
bool success = 1;
|
||||
map<string, SubscriptionError> errors = 2;
|
||||
}
|
||||
|
||||
message Heartbeat {}
|
||||
|
||||
|
||||
// This message is used to tell the App which vehicles are assigned to the current user.
|
||||
// The message is sent when the AppTwin is fully initialized (i.e. when it received the first vcb-response)
|
||||
//
|
||||
// The list of VINs is needed when a user gets unassigned from a vehicle while not connected to an AppTwin
|
||||
// In this case the vehicle would still show in the app the next time the user starts it (see https://appsfactory.atlassian.net/browse/DAIM-3831)
|
||||
// To prevent this, we tell the App which VINs are assigned via this message
|
||||
message AssignedVehicles {
|
||||
repeated string vins = 1;
|
||||
}
|
||||
|
||||
message AcknowledgeAssignedVehicles {}
|
@ -0,0 +1,45 @@
|
||||
syntax = "proto3";
|
||||
package proto;
|
||||
|
||||
option java_package = "com.daimler.mbcarkit.proto";
|
||||
|
||||
message AcknowledgeServiceStatusUpdatesByVIN {
|
||||
int32 sequence_number = 1;
|
||||
}
|
||||
|
||||
message AcknowledgeServiceStatusUpdate {
|
||||
int32 sequence_number = 1;
|
||||
}
|
||||
|
||||
message ServiceStatusUpdatesByVIN {
|
||||
int32 sequence_number = 1;
|
||||
// Updates with VinOrFins
|
||||
map<string, ServiceStatusUpdate> updates = 2;
|
||||
}
|
||||
|
||||
message ServiceStatusUpdate {
|
||||
int32 sequence_number = 1;
|
||||
|
||||
string ciam_id = 7;
|
||||
|
||||
// FinOrVin
|
||||
string vin = 5;
|
||||
|
||||
// when was the event emitted? This is the time of the update,
|
||||
// not when the attributes where changed. To compare attribute changes, you need to look into each attribute timestamp
|
||||
int64 emit_timestamp = 2;
|
||||
|
||||
// When was the event emitted (milliseconds in Unix time)
|
||||
int64 emit_timestamp_in_ms = 8;
|
||||
|
||||
// serviceID -> Status
|
||||
map<int32, ServiceStatus> updates = 6;
|
||||
};
|
||||
|
||||
enum ServiceStatus {
|
||||
SERVICE_STATUS_UNKNOWN = 0;
|
||||
SERVICE_STATUS_ACTIVE = 1;
|
||||
SERVICE_STATUS_INACTIVE = 2;
|
||||
SERVICE_STATUS_ACTIVATION_PENDING = 3;
|
||||
SERVICE_STATUS_DEACTIVATION_PENDING = 4;
|
||||
}
|
153
bundles/org.openhab.binding.mercedesme/proto/user-events.proto
Normal file
@ -0,0 +1,153 @@
|
||||
syntax = "proto3";
|
||||
package proto;
|
||||
|
||||
option java_package = "com.daimler.mbcarkit.proto";
|
||||
|
||||
message AcknowledgeUserDataUpdate {
|
||||
int32 sequence_number = 1;
|
||||
}
|
||||
|
||||
message UserDataUpdate {
|
||||
int32 sequence_number = 1;
|
||||
|
||||
string ciam_id = 2;
|
||||
|
||||
// when was the event emitted? This is the time of the update,
|
||||
// not when the attributes where changed. To compare attribute changes, you need to look into each attribute timestamp
|
||||
int64 emit_timestamp = 3;
|
||||
|
||||
// When was the event emitted (milliseconds in Unix time)
|
||||
int64 emit_timestamp_in_ms = 8;
|
||||
|
||||
CPDUserData old_data = 6;
|
||||
CPDUserData new_data = 7;
|
||||
}
|
||||
|
||||
message AcknowledgeUserVehicleAuthChangedUpdate {
|
||||
int32 sequence_number = 1;
|
||||
}
|
||||
|
||||
message AcknowledgeAbilityToGetVehicleMasterDataFromRestAPI {
|
||||
int32 sequence_number = 1;
|
||||
}
|
||||
|
||||
message UserVehicleAuthChangedUpdate {
|
||||
int32 sequence_number = 1;
|
||||
|
||||
string ciam_id = 2;
|
||||
|
||||
// when was the event emitted? This is the time of the update,
|
||||
// not when the attributes where changed. To compare attribute changes, you need to look into each attribute timestamp
|
||||
int64 emit_timestamp = 3;
|
||||
|
||||
// When was the event emitted (milliseconds in Unix time)
|
||||
int64 emit_timestamp_in_ms = 8;
|
||||
}
|
||||
|
||||
message CPDUserData {
|
||||
string ciam_id = 1;
|
||||
string user_id = 2;
|
||||
string first_name = 3;
|
||||
string last_name1 = 4;
|
||||
string last_name2 = 5;
|
||||
string title = 6;
|
||||
string name_prefix = 7;
|
||||
string middle_initial = 8;
|
||||
string salutation_code = 9;
|
||||
string email = 10;
|
||||
string landline_phone = 11;
|
||||
string mobile_phone_number = 12;
|
||||
string created_at = 13;
|
||||
string created_by = 14;
|
||||
string updated_at = 15;
|
||||
string birthday = 28;
|
||||
string preferred_language_code = 29;
|
||||
string account_country_code = 30;
|
||||
// doc says: TODO
|
||||
string uc_id = 31;
|
||||
bool vip = 32;
|
||||
CPDUserAddress address = 33;
|
||||
CPDUserCommunicationPreference communication_preference = 34;
|
||||
}
|
||||
|
||||
message CPDUserAddress {
|
||||
string country_code = 1;
|
||||
string state = 2;
|
||||
string province = 3;
|
||||
string street = 4;
|
||||
string house_no = 5;
|
||||
string zip_code = 6;
|
||||
string city = 7;
|
||||
string street_type = 8;
|
||||
string house_name = 9;
|
||||
string floor_no = 10;
|
||||
string door_no = 11;
|
||||
string address_line1 = 12;
|
||||
string address_line2 = 13;
|
||||
string address_line3 = 14;
|
||||
string post_office_box = 15;
|
||||
}
|
||||
|
||||
message CPDUserCommunicationPreference {
|
||||
bool contacted_by_phone = 1;
|
||||
bool contacted_by_letter = 2;
|
||||
bool contacted_by_email = 3;
|
||||
bool contacted_by_sms = 4;
|
||||
}
|
||||
|
||||
message AcknowledgeUserPictureUpdate {
|
||||
int32 sequence_number = 1;
|
||||
}
|
||||
|
||||
// Sent after a picture upload/change
|
||||
message UserPictureUpdate {
|
||||
int32 sequence_number = 1;
|
||||
|
||||
// ciam ID
|
||||
string ciam_id = 5;
|
||||
|
||||
// when was the event emitted? This is the time of the update
|
||||
int64 emit_timestamp = 2;
|
||||
|
||||
// When was the event emitted (milliseconds in Unix time)
|
||||
int64 emit_timestamp_in_ms = 6;
|
||||
|
||||
// this timestamp indicates when a message was read from the eventhub
|
||||
int64 eventhub_receive_timestamp = 3;
|
||||
|
||||
// this timestamp indicates when a message was processed in the app twin
|
||||
int64 apptwin_receive_timestamp = 4;
|
||||
}
|
||||
|
||||
message AcknowledgeUserPINUpdate {
|
||||
int32 sequence_number = 1;
|
||||
}
|
||||
|
||||
// Sent after a PIN update
|
||||
message UserPINUpdate {
|
||||
int32 sequence_number = 1;
|
||||
|
||||
// ciam ID
|
||||
string ciam_id = 5;
|
||||
|
||||
// when was the event emitted? This is the time of the update
|
||||
int64 emit_timestamp = 2;
|
||||
|
||||
// When was the event emitted (milliseconds in Unix time)
|
||||
int64 emit_timestamp_in_ms = 6;
|
||||
|
||||
// this timestamp indicates when a message was read from the eventhub
|
||||
int64 eventhub_receive_timestamp = 3;
|
||||
|
||||
// this timestamp indicates when a message was processed in the app twin
|
||||
int64 apptwin_receive_timestamp = 4;
|
||||
}
|
||||
|
||||
// Contains the refreshed jwt of the user
|
||||
message UpdateUserJWTRequest {
|
||||
string jwt = 1;
|
||||
}
|
||||
|
||||
// Ack for the UpdateUserJWTRequest
|
||||
message AcknowledgeUpdateUserJWTRequest {
|
||||
}
|
@ -0,0 +1,611 @@
|
||||
syntax = "proto3";
|
||||
package proto;
|
||||
//import "github.com/gogo/protobuf/gogoproto/gogo.proto";
|
||||
import "gogo.proto";
|
||||
import "google/protobuf/wrappers.proto";
|
||||
|
||||
option (gogoproto.goproto_enum_prefix_all) = true;
|
||||
option java_package = "com.daimler.mbcarkit.proto";
|
||||
|
||||
// Acknowledge the CommandRequest reached the apptwin actor
|
||||
// Websocket <- Apptwin
|
||||
message AcknowledgeCommandRequest {
|
||||
string request_id = 1;
|
||||
}
|
||||
|
||||
// After the command was issued at VVA based on this
|
||||
// command request the call will get a command request
|
||||
// correlation message which matches the request id
|
||||
// with the process id.
|
||||
// Sending direction: App - BFF -> AppTwin
|
||||
message CommandRequest {
|
||||
string vin = 1;
|
||||
|
||||
// Set this id to correlate a CommandStatus
|
||||
// with this command request.
|
||||
string request_id = 7;
|
||||
|
||||
// Temporary backend switch field. Will be removed as soon as all commands are migrated to the VehicleAPI
|
||||
// This field only needs to be set if the command is supported by both API from our backend. If this field is removed
|
||||
// don't forget to set the field 36 to reserved.
|
||||
enum Backend {
|
||||
VVA = 0; // default value
|
||||
VehicleAPI = 1;
|
||||
}
|
||||
Backend backend = 36;
|
||||
|
||||
oneof command {
|
||||
AuxheatStart auxheat_start = 2;
|
||||
AuxheatStop auxheat_stop = 3;
|
||||
AuxheatConfigure auxheat_configure = 4;
|
||||
|
||||
DoorsLock doors_lock = 5;
|
||||
DoorsUnlock doors_unlock = 6;
|
||||
|
||||
SunroofOpen sunroof_open = 9;
|
||||
SunroofClose sunroof_close = 10;
|
||||
SunroofLift sunroof_lift = 11;
|
||||
SunroofMove sunroof_move = 47;
|
||||
|
||||
WindowsOpen windows_open = 12;
|
||||
WindowsClose windows_close = 13;
|
||||
WindowsVentilate windows_ventilate = 43;
|
||||
WindowsMove windows_move = 44;
|
||||
|
||||
EngineStart engine_start = 19;
|
||||
EngineStop engine_stop = 20;
|
||||
|
||||
ZEVPreconditioningStart zev_preconditioning_start = 21;
|
||||
ZEVPreconditioningStop zev_preconditioning_stop = 22;
|
||||
ZEVPreconditioningConfigure zev_precondition_configure = 25;
|
||||
ZEVPreconditioningConfigureSeats zev_precondition_configure_seats = 26;
|
||||
|
||||
SpeedalertStart speedalert_start = 23;
|
||||
SpeedalertStop speedalert_stop = 24;
|
||||
|
||||
BatteryChargeProgramConfigure battery_charge_program = 27;
|
||||
BatteryMaxSocConfigure battery_max_soc = 28;
|
||||
|
||||
ChargeProgramConfigure charge_program_configure = 34;
|
||||
ChargeControlConfigure charge_control_configure = 40;
|
||||
|
||||
ChargeOptConfigure charge_opt_configure = 29;
|
||||
ChargeOptStart charge_opt_start = 30;
|
||||
ChargeOptStop charge_opt_stop = 31;
|
||||
|
||||
TemperatureConfigure temperature_configure = 32;
|
||||
|
||||
WeekProfileConfigure week_profile_configure = 33;
|
||||
WeekProfileConfigureV2 week_profile_configure_v2 = 41;
|
||||
|
||||
SigPosStart sigpos_start = 35;
|
||||
|
||||
TheftalarmConfirmDamagedetection theftalarm_confirm_damagedetection = 8;
|
||||
TheftalarmDeselectDamagedetection theftalarm_deselect_damagedetection= 14;
|
||||
TheftalarmDeselectInterior theftalarm_deselect_interior = 15;
|
||||
TheftalarmDeselectTow theftalarm_deselect_tow = 16;
|
||||
TheftalarmSelectDamagedetection theftalarm_select_damagedetection = 17;
|
||||
TheftalarmSelectInterior theftalarm_select_interior = 18;
|
||||
TheftalarmSelectTow theftalarm_select_tow = 37;
|
||||
TheftalarmStart theftalarm_start = 38;
|
||||
TheftalarmStop theftalarm_stop = 39;
|
||||
|
||||
AutomaticValetParkingActivate automatic_valet_parking_activate = 42;
|
||||
|
||||
ChargeFlapUnlock charge_flap_unlock = 45;
|
||||
ChargeCouplerUnlock charge_coupler_unlock = 46;
|
||||
|
||||
DeactivateVehicleKeys deactivate_vehicle_keys = 48;
|
||||
ActivateVehicleKeys activate_vehicle_keys = 49;
|
||||
}
|
||||
}
|
||||
|
||||
message DeactivateVehicleKeys {
|
||||
string pin = 1;
|
||||
|
||||
int64 expiration_unix = 2;
|
||||
|
||||
string expiration_seconds = 3 [ json_name = "expirationSeconds" ];
|
||||
string expiration_milliseconds = 4 [ json_name = "expirationMilliseconds" ];
|
||||
}
|
||||
|
||||
message ActivateVehicleKeys {
|
||||
string pin = 1;
|
||||
|
||||
int64 expiration_unix = 2;
|
||||
|
||||
string expiration_seconds = 3 [ json_name = "expirationSeconds" ];
|
||||
string expiration_milliseconds = 4 [ json_name = "expirationMilliseconds" ];
|
||||
}
|
||||
|
||||
message AuxheatStart {}
|
||||
message AuxheatStop {}
|
||||
message AuxheatConfigure {
|
||||
|
||||
enum Selection {
|
||||
NO_SELECTION = 0;
|
||||
TIME_1 = 1;
|
||||
TIME_2 = 2;
|
||||
TIME_3 = 3;
|
||||
}
|
||||
|
||||
Selection time_selection = 1 [ json_name = "auxheattimeselection" ];
|
||||
|
||||
// Minutes from midnight.
|
||||
int32 time_1 = 2 [ json_name = "auxheattime1" ];
|
||||
|
||||
// Minutes from midnight.
|
||||
int32 time_2 = 3 [ json_name = "auxheattime2" ];
|
||||
|
||||
// Minutes from midnight.
|
||||
int32 time_3 = 4 [ json_name = "auxheattime3" ];
|
||||
}
|
||||
|
||||
enum Door {
|
||||
// the JSON enum values are lowercase, but lowercase values are not exported in golang, so
|
||||
// we allow aliasing all values.
|
||||
option allow_alias = true;
|
||||
|
||||
// the lowercase versions are for json (de)serialization purposes only. The upper case version should be the preferred
|
||||
// enum values to be used in code.
|
||||
// These definitions need to come before upper case versions
|
||||
unknown_door = 0;
|
||||
frontleft = 1;
|
||||
frontright = 2;
|
||||
rearleft = 3;
|
||||
rearright = 4;
|
||||
trunk = 5;
|
||||
fuelflap = 6;
|
||||
chargeflap = 7;
|
||||
chargecoupler = 8;
|
||||
|
||||
UNKNOWN_DOOR = 0;
|
||||
FRONT_LEFT = 1;
|
||||
FRONT_RIGHT = 2;
|
||||
REAR_LEFT = 3;
|
||||
REAR_RIGHT = 4;
|
||||
TRUNK = 5;
|
||||
FUEL_FLAP = 6;
|
||||
CHARGE_FLAP = 7;
|
||||
CHARGE_COUPLER = 8;
|
||||
}
|
||||
|
||||
message DoorsLock {
|
||||
// doors / flaps to unlock (only supported by TCU type RAMSES)
|
||||
// leave empty to target all doors
|
||||
repeated Door doors = 1;
|
||||
}
|
||||
|
||||
message DoorsUnlock {
|
||||
string pin = 1;
|
||||
// doors / flaps to unlock (only supported by TCU type RAMSES)
|
||||
// leave empty to target all doors
|
||||
repeated Door doors = 2;
|
||||
}
|
||||
|
||||
message EngineStart {
|
||||
string pin = 1;
|
||||
}
|
||||
|
||||
message EngineStop {}
|
||||
|
||||
message SunroofOpen {
|
||||
string pin = 1;
|
||||
}
|
||||
message SunroofClose {}
|
||||
message SunroofLift {
|
||||
string pin = 1;
|
||||
}
|
||||
|
||||
message SunroofMove {
|
||||
string pin = 1;
|
||||
google.protobuf.Int32Value sunroof = 2 [ json_name = "sunroof" ];
|
||||
google.protobuf.Int32Value sunroof_blind_front = 3 [ json_name = "sunroofblindfront" ];
|
||||
google.protobuf.Int32Value sunroof_blind_rear = 4 [ json_name = "sunroofblindrear" ];
|
||||
}
|
||||
|
||||
message WindowsOpen {
|
||||
string pin = 1;
|
||||
}
|
||||
message WindowsClose {}
|
||||
|
||||
message WindowsVentilate {
|
||||
string pin = 1;
|
||||
}
|
||||
|
||||
message WindowsMove {
|
||||
string pin = 1;
|
||||
google.protobuf.Int32Value front_left = 2 [ json_name = "windowfrontleft" ];
|
||||
google.protobuf.Int32Value front_right = 3 [ json_name = "windowfrontright" ];
|
||||
google.protobuf.Int32Value rear_blind = 4 [ json_name = "windowrearblind" ];
|
||||
google.protobuf.Int32Value rear_left = 5 [ json_name = "windowrearleft" ];
|
||||
google.protobuf.Int32Value rear_left_blind = 6 [ json_name = "windowrearleftblind" ];
|
||||
google.protobuf.Int32Value rear_right = 7 [ json_name = "windowrearright" ];
|
||||
google.protobuf.Int32Value rear_right_blind = 8 [ json_name = "windowrearrightblind" ];
|
||||
}
|
||||
|
||||
message SpeedalertStart {
|
||||
int32 threshold = 1 [ json_name = "speedAlertThreshold" ];
|
||||
int64 alert_end_time = 2 [ json_name = "speedAlertEndTime" ];
|
||||
}
|
||||
message SpeedalertStop {}
|
||||
|
||||
// --- Vehicle API commands
|
||||
|
||||
enum ZEVPreconditioningType {
|
||||
// the JSON enum values are lowercase, but lowercase values are not exported in golang, so
|
||||
// we allow aliasing all values.
|
||||
option allow_alias = true;
|
||||
|
||||
// the lowercase versions are for json parsing purposes only. The upper case version should be the preferred
|
||||
// enum values to be used in code.
|
||||
// These definitions need to come before upper case versions
|
||||
unknown_zev_preconditioning_command_type = 0;
|
||||
immediate = 1;
|
||||
departure = 2;
|
||||
now = 3;
|
||||
departureWeekly = 4;
|
||||
|
||||
// the uppercase versions are here to have exported values
|
||||
// The given preconditioning command type is unknown
|
||||
UNKNOWN_ZEV_PRECONDITIONING_COMMAND_TYPE = 0;
|
||||
|
||||
// starts immediate preconditioning
|
||||
IMMEDIATE = 1;
|
||||
|
||||
// starts preconditioning at departure time (requires a departure time to be provided in ZEVPreconditioningStart)
|
||||
DEPARTURE = 2;
|
||||
|
||||
// start right away (departure time is ignored)
|
||||
NOW = 3;
|
||||
|
||||
// starts preconditioning for a configured weekly profile (does NOT require a departure time to be provided)
|
||||
DEPARTURE_WEEKLY = 4;
|
||||
|
||||
}
|
||||
|
||||
message ZEVPreconditioningStart {
|
||||
int32 departure_time = 1 [ json_name = "departuretime" ];
|
||||
ZEVPreconditioningType type = 2 [ json_name = "type" ];
|
||||
}
|
||||
|
||||
message ZEVPreconditioningStop { ZEVPreconditioningType type = 2 [ json_name = "type" ]; }
|
||||
|
||||
// Configure preconditioning
|
||||
message ZEVPreconditioningConfigure {
|
||||
enum DepartureTimeMode {
|
||||
DISABLED = 0;
|
||||
SINGLE_DEPARTURE = 1;
|
||||
WEEKLY_DEPARTURE = 2;
|
||||
}
|
||||
DepartureTimeMode departure_time_mode = 1 [ json_name = "departureTimeMode" ];
|
||||
|
||||
int32 departure_time = 3 [ json_name = "departuretime" ];
|
||||
}
|
||||
|
||||
// Configure which seats should be preconditioned.
|
||||
// Currently, the only available options are to precondition all seats or only the front-left seat
|
||||
message ZEVPreconditioningConfigureSeats {
|
||||
bool front_left = 1 [ json_name = "precondSeatFrontLeft" ];
|
||||
bool front_right = 2 [ json_name = "precondSeatFrontRight" ];
|
||||
bool rear_left = 3 [ json_name = "precondSeatRearLeft" ];
|
||||
bool rear_right = 4 [ json_name = "precondSeatRearRight" ];
|
||||
}
|
||||
|
||||
// Configure the charge program
|
||||
message BatteryChargeProgramConfigure {
|
||||
enum ChargeProgram {
|
||||
DEFAULT = 0;
|
||||
INSTANT = 1;
|
||||
}
|
||||
ChargeProgram charge_program = 1 [ json_name = "chargeprogram" ];
|
||||
}
|
||||
|
||||
// Configure the maximum value for the state of charge of the HV battery
|
||||
message BatteryMaxSocConfigure {
|
||||
// Values need to be between 50 and 100 and divisible by ten
|
||||
int32 max_soc = 1 [ json_name = "maxsoc" ];
|
||||
}
|
||||
|
||||
// Select the given charge program and enables the consumer to configure it.
|
||||
message ChargeProgramConfigure {
|
||||
enum ChargeProgram {
|
||||
DEFAULT_CHARGE_PROGRAM = 0;
|
||||
// Instant charge program should not be used
|
||||
// INSTANT_CHARGE_PROGRAM = 1;
|
||||
HOME_CHARGE_PROGRAM = 2;
|
||||
WORK_CHARGE_PROGRAM = 3;
|
||||
}
|
||||
ChargeProgram charge_program = 1 [ json_name = "chargeprogram" ];
|
||||
|
||||
// Values need to be between 50 and 100 and divisible by ten
|
||||
// Maximum value for the state of charge of the HV battery [in %].
|
||||
// Valid value range = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
|
||||
google.protobuf.Int32Value max_soc = 2 [ json_name = "maxsoc" ];
|
||||
|
||||
// unlock the plug after charging is finished
|
||||
// Denotes whether the charge cable should be unlocked automatically if the HV battery is fully charged resp. charged til Max. SoC value.
|
||||
// true - unlock automatically, false - do not unlock automatically
|
||||
// can only be used if chargeprogram is set to home or work. Otherwise it will be ignored.
|
||||
google.protobuf.BoolValue auto_unlock = 3 [ json_name = "autounlock" ];
|
||||
|
||||
// automatically switch between home and work program, based on the location of the car
|
||||
// Denotes whether location based charging should be used.
|
||||
// true - use location based charging, false - do not use location based charging
|
||||
// can only be used if chargeprogram is set to home or work. Otherwise it will be ignored.
|
||||
google.protobuf.BoolValue location_based_charging = 4 [ json_name = "locationbasedcharging" ];
|
||||
|
||||
// enable or disable week-profile
|
||||
// Denotes whether weekly profile (aka. weekprofile) should be used.
|
||||
// true - use weekly profile, false - do not use weekly profile
|
||||
// The parameter weekprofile should not be used.
|
||||
// google.protobuf.BoolValue weekly_profile = 5 [ json_name = "weeklyprofile" ];
|
||||
|
||||
// enable or disable clocktimer
|
||||
google.protobuf.BoolValue clock_timer = 6 [ json_name = "clocktimer" ];
|
||||
|
||||
// enable or disable ecocharging
|
||||
google.protobuf.BoolValue eco_charging = 7 [ json_name = "ecocharging" ];
|
||||
}
|
||||
|
||||
// This is an experimental command
|
||||
message ChargeControlConfigure {
|
||||
// Enables/Disables bidrectional charging
|
||||
google.protobuf.BoolValue bi_charging_enabled = 1 [ json_name = "bidichargingenabled" ];
|
||||
|
||||
// Sets the charging power in kW with a resolution of 0.1 kW. The value has an offset of -100 kW. So
|
||||
// a value of 0 is equivalent to -100 kW.
|
||||
google.protobuf.FloatValue charging_power = 2 [ json_name = "chargingpower" ];
|
||||
|
||||
// must not be above max_soc
|
||||
google.protobuf.Int32Value min_soc = 3 [ json_name = "minsoc" ];
|
||||
}
|
||||
|
||||
// Provide functionality to initiate a charge optimization configuration
|
||||
message ChargeOptConfigure {
|
||||
message Tariff {
|
||||
enum Rate {
|
||||
INVALID_PRICE = 0;
|
||||
LOW_PRICE = 33;
|
||||
NORMAL_PRICE = 44;
|
||||
HIGH_PRICE = 66;
|
||||
}
|
||||
Rate rate = 1 [ json_name = "rate" ];
|
||||
// Time in seconds after 00:00
|
||||
int32 time = 2 [ json_name = "time" ];
|
||||
}
|
||||
|
||||
repeated Tariff weekday_tariff = 1 [ json_name = "weekdaytariff" ];
|
||||
repeated Tariff weekend_tariff = 2 [ json_name = "weekendtariff" ];
|
||||
}
|
||||
|
||||
// Provide the functionality to start the charge optimization function in the vehicle
|
||||
message ChargeOptStart {
|
||||
// empty
|
||||
}
|
||||
|
||||
// Provide the functionality to stop the charge optimization function in the vehicle
|
||||
message ChargeOptStop {
|
||||
// empty
|
||||
}
|
||||
|
||||
// Set the temperature points of the vehicle
|
||||
message TemperatureConfigure {
|
||||
message TemperaturePoint {
|
||||
reserved 2;
|
||||
|
||||
enum Zone {
|
||||
// the JSON enum values are lowercase, but lowercase values are not exported in golang, so
|
||||
// we allow aliasing all values.
|
||||
option allow_alias = true;
|
||||
|
||||
// the lowercase versions are for json parsing purposes only. The upper case version should be the preferred
|
||||
// enum values to be used in code.
|
||||
// These definitions need to come before upper case versions
|
||||
unknown = 0;
|
||||
frontLeft = 1;
|
||||
frontRight = 2;
|
||||
frontCenter = 3;
|
||||
rearLeft = 4;
|
||||
rearRight = 5;
|
||||
rearCenter = 6;
|
||||
rear2Left = 7;
|
||||
rear2Right = 8;
|
||||
rear2Center = 9;
|
||||
// PLEASE BE AWARE OF THE FOLLOWING BEFORE ADDING NEW ZONES:
|
||||
// Currently there is a bug in vehicle API, that we need to send the zones in the correct order. Otherwise the request will be rejected.
|
||||
// The order needs to be like the following:
|
||||
// Front before rear before rear2
|
||||
// Left before right - There is no center zone if there are left and right zones in this row
|
||||
// As this is already the order like specified here, this needs to be considered on adding new zones.
|
||||
|
||||
UNKNOWN_ZONE = 0;
|
||||
FRONT_LEFT = 1;
|
||||
FRONT_RIGHT = 2;
|
||||
FRONT_CENTER = 3;
|
||||
REAR_LEFT = 4;
|
||||
REAR_RIGHT = 5;
|
||||
REAR_CENTER = 6;
|
||||
REAR_2_LEFT = 7;
|
||||
REAR_2_RIGHT = 8;
|
||||
REAR_2_CENTER = 9;
|
||||
// PLEASE BE AWARE OF THE FOLLOWING BEFORE ADDING NEW ZONES:
|
||||
// Currently there is a bug in vehicle API, that we need to send the zones in the correct order. Otherwise the request will be rejected.
|
||||
// The order needs to be like the following:
|
||||
// Front before rear before rear2
|
||||
// Left before right - There is no center zone if there are left and right zones in this row
|
||||
// As this is already the order like specified here, this needs to be considered on adding new zones.
|
||||
}
|
||||
Zone zone = 1 [ json_name = "zone" ];
|
||||
|
||||
double temperature_in_celsius = 3 [ json_name = "temp" ];
|
||||
}
|
||||
|
||||
repeated TemperaturePoint temperature_points = 1 [ json_name = "temperaturePoints" ];
|
||||
}
|
||||
|
||||
// Set the weekprofile for the weekly departure time settings
|
||||
message WeekProfileConfigure {
|
||||
message WeeklySetHU {
|
||||
enum Day {
|
||||
MONDAY = 0;
|
||||
TUESDAY = 1;
|
||||
WEDNESDAY = 2;
|
||||
THURSDAY = 3;
|
||||
FRIDAY = 4;
|
||||
SATURDAY = 5;
|
||||
SUNDAY = 6;
|
||||
}
|
||||
Day day = 1 [ json_name = "day" ];
|
||||
// Time in minutes after 00:00
|
||||
int32 time = 2 [ json_name = "time" ];
|
||||
}
|
||||
|
||||
repeated WeeklySetHU weekly_set_hu = 1 [ json_name = "weeklySetHU" ];
|
||||
}
|
||||
|
||||
// Set the week profile for the weekly departure time settings version 2
|
||||
message WeekProfileConfigureV2 {
|
||||
// * The whole list of timeProfiles must always be provided
|
||||
repeated TimeProfile time_profiles = 1 [ json_name = "timeprofiles" ];
|
||||
}
|
||||
|
||||
message TimeProfile {
|
||||
//=> only if time profile entry is unchanged, do not provide attribute "id" if new profile entry shall be added
|
||||
// If a new time profile shall be added: do not provide the ID => ID will be set by MIC / vehicle
|
||||
google.protobuf.Int32Value identifier = 1 [ json_name = "id" ];
|
||||
|
||||
// Hour after midnight range [0, 23]
|
||||
google.protobuf.Int32Value hour = 2 [json_name = "hour" ];
|
||||
|
||||
// Minute after full hour range [0, 59]
|
||||
google.protobuf.Int32Value minute = 3 [json_name = "min" ];
|
||||
|
||||
// Days for which the above time should be applied
|
||||
repeated TimeProfileDay days = 4 [json_name = "day" ];
|
||||
|
||||
// Whether this profile entry is active or not
|
||||
google.protobuf.BoolValue active = 5 [json_name = "active" ];
|
||||
|
||||
// If a timeProfile is changed or added the respective applicationId must be provided by the SDK
|
||||
// 11 = Internal Apps
|
||||
// 12 = External Apps
|
||||
int32 application_identifier = 6 [ json_name = "applicationId" ];
|
||||
}
|
||||
|
||||
enum TimeProfileDay {
|
||||
option allow_alias = true;
|
||||
// the short versions are for json (en)coding purposes only. The upper case version should be the preferred
|
||||
// enum values to be used in code.
|
||||
// These definitions need to come before upper case versions
|
||||
Mo = 0;
|
||||
Tu = 1;
|
||||
We = 2;
|
||||
Th = 3;
|
||||
Fr = 4;
|
||||
Sa = 5;
|
||||
Su = 6;
|
||||
|
||||
MONDAY = 0;
|
||||
TUESDAY = 1;
|
||||
WEDNESDAY = 2;
|
||||
THURSDAY = 3;
|
||||
FRIDAY = 4;
|
||||
SATURDAY = 5;
|
||||
SUNDAY = 6;
|
||||
}
|
||||
|
||||
// Invoke the Remote Vehicle Finder for signalling the vehicle’s position with lights, horn or panic alarm.
|
||||
message SigPosStart {
|
||||
// Value needs to be between 0 and 30. The default is 0.
|
||||
// Only allowed for RAMSES
|
||||
int32 horn_repeat = 1 [ json_name = "hornRepeat" ];
|
||||
|
||||
// Only allowed for RAMSES
|
||||
enum HornType {
|
||||
HORN_OFF = 0;
|
||||
HORN_LOW_VOLUME = 1;
|
||||
HORN_HIGH_VOLUME = 2;
|
||||
}
|
||||
HornType horn_type = 2 [ json_name = "hornType" ];
|
||||
|
||||
// Only allowed for RAMSES
|
||||
enum LightType {
|
||||
LIGHT_OFF = 0;
|
||||
DIPPED_HEAD_LIGHT = 1;
|
||||
WARNING_LIGHT = 2;
|
||||
}
|
||||
LightType light_type = 3 [ json_name = "lightType" ];
|
||||
|
||||
// Value needs to be between 0 and 10. It indicates how long the light should be switched on.
|
||||
int32 sigpos_duration = 4 [ json_name = "sigposDuration" ];
|
||||
|
||||
enum SigposType {
|
||||
LIGHT_ONLY = 0;
|
||||
HORN_ONLY = 1; // Only allowed for RAMSES
|
||||
LIGHT_AND_HORN = 2; // Only allowed for RAMSES
|
||||
PANIC_ALARM = 3; // Only allowed for HERMES
|
||||
}
|
||||
SigposType sigpos_type = 5 [ json_name = "sigposType" ];
|
||||
}
|
||||
|
||||
// Confirm the detected parking bump
|
||||
message TheftalarmConfirmDamagedetection {
|
||||
// empty
|
||||
}
|
||||
|
||||
// Provide the functionality to deselect the parking damage detection sensor
|
||||
message TheftalarmDeselectDamagedetection {
|
||||
// empty
|
||||
}
|
||||
|
||||
// Provide the functionality to deselect the interior protection sensor
|
||||
message TheftalarmDeselectInterior {
|
||||
// empty
|
||||
}
|
||||
|
||||
// Provide the functionality to deselect the tow protection sensor
|
||||
message TheftalarmDeselectTow {
|
||||
// empty
|
||||
}
|
||||
|
||||
// Provide the functionality to select the parking damage detection sensor
|
||||
message TheftalarmSelectDamagedetection {
|
||||
// empty
|
||||
}
|
||||
|
||||
// Provide the functionality to select the interior protection sensor
|
||||
message TheftalarmSelectInterior {
|
||||
// empty
|
||||
}
|
||||
|
||||
// Provide the functionality to select the tow protection sensor
|
||||
message TheftalarmSelectTow {
|
||||
// empty
|
||||
}
|
||||
|
||||
// Provide the functionality to trigger an alarm that lasts for "alarm_duration" seconds
|
||||
message TheftalarmStart {
|
||||
// Specify how many seconds the alarm should be switched on
|
||||
int32 alarm_duration_in_seconds = 1 [ json_name = "alarmduration" ];
|
||||
}
|
||||
|
||||
// Provide the functionality to deactivate an active/ongoing alarm
|
||||
message TheftalarmStop {
|
||||
// empty
|
||||
}
|
||||
|
||||
enum DriveType {
|
||||
UNKNOWN_DRIVE_TYPE = 0;
|
||||
PICK_UP = 1;
|
||||
DROP_OFF = 2;
|
||||
}
|
||||
|
||||
message AutomaticValetParkingActivate {
|
||||
string booking_id = 1 [ json_name = "bookingId" ];
|
||||
DriveType drive_type = 2 [ json_name = "driveType" ];
|
||||
}
|
||||
|
||||
message ChargeFlapUnlock {}
|
||||
|
||||
message ChargeCouplerUnlock {}
|
@ -0,0 +1,457 @@
|
||||
syntax = "proto3";
|
||||
package proto;
|
||||
import "service-activation.proto";
|
||||
import "user-events.proto";
|
||||
import "vehicle-commands.proto";
|
||||
import "protos.proto";
|
||||
import "vehicleapi.proto";
|
||||
|
||||
option java_package = "com.daimler.mbcarkit.proto";
|
||||
|
||||
// Sending direction: App <- BFF <- AppTwin
|
||||
message VEPUpdate {
|
||||
|
||||
int32 sequence_number = 1;
|
||||
|
||||
string vin = 2;
|
||||
|
||||
// indicates whether this is a full update of VEP-attributes.
|
||||
// All attributes cached in the FE should be erased and completely
|
||||
// replaced by this push.
|
||||
bool full_update = 15;
|
||||
|
||||
// when was the event emitted? This is the time of the update (unix timestamp in seconds), (deprecated)
|
||||
// not when the attributes where changed. To compare attribute changes, you need to look into each attribute timestamp
|
||||
int64 emit_timestamp = 10;
|
||||
|
||||
// when was the event emitted? This is the time of the update (unix timestamp in milliseconds),
|
||||
int64 emit_timestamp_in_ms = 14;
|
||||
|
||||
// the attribute changes are a list of changed attributes
|
||||
map<string, VehicleAttributeStatus> attributes = 11;
|
||||
|
||||
}
|
||||
|
||||
// Part of a VEPUpdate
|
||||
// Sending direction: App <- BFF <- AppTwin
|
||||
message VehicleAttributeStatus {
|
||||
// time of the attribute change in the car as unix timestamp in seconds with UTC timezone (deprecated)
|
||||
int64 timestamp = 1 [ deprecated = true ];
|
||||
// time of the attribute change in the car as unix timestamp in milliseconds with UTC timezone
|
||||
int64 timestamp_in_ms = 10;
|
||||
bool changed = 2;
|
||||
int32 status = 3;
|
||||
|
||||
enum CombustionConsumptionUnit {
|
||||
UNSPECIFIED_COMBUSTION_CONSUMPTION_UNIT = 0;
|
||||
// Liter per 100 km
|
||||
LITER_PER_100KM = 1;
|
||||
// Kilometers per liter
|
||||
KM_PER_LITER = 2;
|
||||
// Miles Per imperial gallon
|
||||
MPG_UK = 3;
|
||||
// Miles Per US gallon
|
||||
MPG_US = 4;
|
||||
}
|
||||
|
||||
enum ElectricityConsumptionUnit {
|
||||
UNSPECIFIED_ELECTRICITY_CONSUMPTION_UNIT = 0;
|
||||
// kWh per 100 km
|
||||
KWH_PER_100KM = 1;
|
||||
// Kilometers per kWh
|
||||
KM_PER_KWH = 2;
|
||||
// kWh per 100 miles
|
||||
KWH_PER_100MI = 3;
|
||||
// miles per kWh
|
||||
M_PER_KWH = 4;
|
||||
// Miles per gallon gasoline equivalent
|
||||
MPGE = 5;
|
||||
}
|
||||
|
||||
enum GasConsumptionUnit {
|
||||
UNSPECIFIED_GAS_CONSUMPTION_UNIT = 0;
|
||||
// kG per 100 km
|
||||
KG_PER_100KM = 1;
|
||||
// km per kg
|
||||
KM_PER_KG = 2;
|
||||
// miles per kg
|
||||
M_PER_KG = 3;
|
||||
}
|
||||
|
||||
enum SpeedDistanceUnit {
|
||||
option deprecated = true; // use speed unit / length unit instead
|
||||
|
||||
UNSPECIFIED_SPEED_DISTANCE_UNIT = 0;
|
||||
// km/h, distance unit: km
|
||||
KM_PER_H = 1;
|
||||
// mph, distance unit: miles
|
||||
M_PER_H = 2;
|
||||
}
|
||||
|
||||
enum SpeedUnit {
|
||||
UNSPECIFIED_SPEED_UNIT = 0;
|
||||
// kilometers per hour
|
||||
KM_PER_HOUR = 1;
|
||||
// miles per hour
|
||||
M_PER_HOUR = 2;
|
||||
}
|
||||
|
||||
enum DistanceUnit {
|
||||
UNSPECIFIED_DISTANCE_UNIT = 0;
|
||||
KILOMETERS = 1;
|
||||
MILES = 2;
|
||||
}
|
||||
|
||||
enum TemperatureUnit {
|
||||
UNSPECIFIED_TEMPERATURE_UNIT = 0;
|
||||
CELSIUS = 1;
|
||||
FAHRENHEIT = 2;
|
||||
}
|
||||
|
||||
enum PressureUnit {
|
||||
UNSPECIFIED_PRESSURE_UNIT = 0;
|
||||
KPA = 1 ;
|
||||
BAR = 2;
|
||||
// Pounds per square inch
|
||||
PSI = 3;
|
||||
}
|
||||
|
||||
enum RatioUnit {
|
||||
UNSPECIFIED_RATIO_UNIT = 0;
|
||||
PERCENT = 1;
|
||||
}
|
||||
|
||||
enum ClockHourUnit {
|
||||
UNSPECIFIED_CLOCK_HOUR_UNIT = 0;
|
||||
// 12h (AM/PM)
|
||||
T12H = 1;
|
||||
// 24h
|
||||
T24H = 2;
|
||||
}
|
||||
|
||||
// A list of service ids for which this attribute was sent
|
||||
// this field ist just used backend internally and will always
|
||||
// be empty when sent out to the client.
|
||||
repeated int32 service_ids = 30;
|
||||
|
||||
string display_value = 11;
|
||||
oneof display_unit {
|
||||
CombustionConsumptionUnit combustion_consumption_unit = 12;
|
||||
GasConsumptionUnit gas_consumption_unit = 13;
|
||||
ElectricityConsumptionUnit electricity_consumption_unit = 14;
|
||||
SpeedDistanceUnit speed_distance_unit = 15 [ deprecated = true ]; // use speed unit / length unit instead
|
||||
SpeedUnit speed_unit = 25;
|
||||
DistanceUnit distance_unit = 26;
|
||||
TemperatureUnit temperature_unit = 16;
|
||||
PressureUnit pressure_unit = 17;
|
||||
RatioUnit ratio_unit = 18;
|
||||
ClockHourUnit clock_hour_unit = 19;
|
||||
}
|
||||
|
||||
oneof attribute_type {
|
||||
int64 int_value = 4;
|
||||
bool bool_value = 5;
|
||||
string string_value = 6;
|
||||
double double_value = 7;
|
||||
bool nil_value = 8;
|
||||
string unsupported_value = 9;
|
||||
TemperaturePointsValue temperature_points_value = 20;
|
||||
WeekdayTariffValue weekday_tariff_value = 21;
|
||||
WeekendTariffValue weekend_tariff_value = 22;
|
||||
StateOfChargeProfileValue state_of_charge_profile_value = 23;
|
||||
WeeklySettingsHeadUnitValue weekly_settings_head_unit_value = 24;
|
||||
SpeedAlertConfigurationValue speed_alert_configuration_value = 27;
|
||||
EcoHistogramValue eco_histogram_value = 28;
|
||||
WeeklyProfileValue weekly_profile_value = 29;
|
||||
ChargeProgramsValue charge_programs_value = 31;
|
||||
}
|
||||
}
|
||||
|
||||
message ChargeProgramsValue {
|
||||
repeated ChargeProgramParameters charge_program_parameters = 1;
|
||||
}
|
||||
|
||||
enum ChargeProgram {
|
||||
DEFAULT_CHARGE_PROGRAM = 0;
|
||||
INSTANT_CHARGE_PROGRAM = 1;
|
||||
HOME_CHARGE_PROGRAM = 2;
|
||||
WORK_CHARGE_PROGRAM = 3;
|
||||
}
|
||||
|
||||
message ChargeProgramParameters {
|
||||
ChargeProgram charge_program = 1 [ json_name = "chargeprogram" ];
|
||||
|
||||
// Values need to be between 50 and 100 and divisible by ten
|
||||
// Maximum value for the state of charge of the HV battery [in %].
|
||||
// Valid value range = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
|
||||
int32 max_soc = 2 [ json_name = "maxSoc" ];
|
||||
|
||||
// unlock the plug after charging is finished
|
||||
// Denotes whether the charge cable should be unlocked automatically if the HV battery is fully charged resp. charged til Max. SoC value.
|
||||
// true - unlock automatically, false - do not unlock automatically
|
||||
// can only be used if chargeprogram is set to home or work. Otherwise it will be ignored.
|
||||
bool auto_unlock = 3 [ json_name = "autounlock" ];
|
||||
|
||||
// automatically switch between home and work program, based on the location of the car
|
||||
// Denotes whether location based charging should be used.
|
||||
// true - use location based charging, false - do not use location based charging
|
||||
// can only be used if chargeprogram is set to home or work. Otherwise it will be ignored.
|
||||
bool location_based_charging = 4 [ json_name = "locationbasedcharging" ];
|
||||
|
||||
// enable or disable week-profile
|
||||
// Denotes whether weekly profile (aka. weekprofile) should be used.
|
||||
// true - use weekly profile, false - do not use weekly profile
|
||||
|
||||
bool weekly_profile = 5 [ json_name = "weeklyprofile" ];
|
||||
bool clockTimer = 6 [ json_name = "clockTimer" ];
|
||||
int32 max_charging_current = 7 [ json_name = "MaxChargingCurrent" ];
|
||||
bool eco_charging = 8 [ json_name = "EcoCharging" ];
|
||||
}
|
||||
|
||||
// Same as VehicleAPI.AttributeStatus but with slightly different names. The VehicleAPI.AttributeStatus enum values
|
||||
// can't be changed because they are used to automatically parse the vehicleAPI responses. Adding type aliases would
|
||||
// confuse the contributions developers, so we added another attribute status enum
|
||||
enum AttributeStatus {
|
||||
// Value is set and valid
|
||||
VALUE_VALID = 0;
|
||||
// Value has not yet been received from the vehicle (but sensor etc. should be available)
|
||||
VALUE_NOT_RECEIVED = 1;
|
||||
// Value has been retrieved from vehicle but is invalid (marked as invalid by DaiVB backend)
|
||||
VALUE_INVALID = 3;
|
||||
// Vehicle does not support this attribute (e.g. does not have the sensor etc.)
|
||||
VALUE_NOT_AVAILABLE = 4;
|
||||
}
|
||||
|
||||
message WeeklyProfileValue {
|
||||
bool single_time_profile_entries_activatable = 1 [ json_name = "singleTimeProfileEntriesActivatable" ];
|
||||
|
||||
int32 max_number_of_weekly_time_profile_slots = 2 [ json_name = "maxNumberOfWeeklyTimeProfileSlots" ];
|
||||
|
||||
int32 max_number_of_time_profiles = 3 [ json_name = "maxNumberOfTimeProfiles" ];
|
||||
|
||||
int32 current_number_of_time_profile_slots = 4 [ json_name = "currentNumberOfTimeProfileSlots" ];
|
||||
|
||||
int32 current_number_of_time_profiles = 5 [ json_name = "currentNumberOfTimeProfiles" ];
|
||||
|
||||
repeated VVRTimeProfile time_profiles = 6 [ json_name = "timeProfiles" ];
|
||||
}
|
||||
|
||||
// VVRTimeProfile is almost identical to the "TimeProfile" message with the exception that the identifier is not optional.
|
||||
message VVRTimeProfile {
|
||||
// unique id of this time profile entry
|
||||
int32 identifier = 1 [ json_name = "id" ];
|
||||
|
||||
// Hour after midnight range [0, 23]
|
||||
int32 hour = 2 [json_name = "hour" ];
|
||||
|
||||
// Minute after full hour range [0, 59]
|
||||
int32 minute = 3 [json_name = "min" ];
|
||||
|
||||
// Days for which the above time should be applied
|
||||
repeated TimeProfileDay days = 4 [json_name = "day" ];
|
||||
|
||||
// Whether this profile entry is active or not
|
||||
bool active = 5 [json_name = "active" ];
|
||||
|
||||
// If a timeProfile is changed or added the respective applicationId must be provided by SDK
|
||||
// 11 = Internal Apps
|
||||
// 12 = External Apps
|
||||
int32 application_identifier = 6 [ json_name = "applicationId" ];
|
||||
}
|
||||
|
||||
message EcoHistogramValue {
|
||||
repeated EcoHistogramBin eco_histogram_bins = 1;
|
||||
}
|
||||
|
||||
message EcoHistogramBin {
|
||||
double interval = 1;
|
||||
double value = 2;
|
||||
}
|
||||
|
||||
message SpeedAlertConfigurationValue {
|
||||
repeated SpeedAlertConfiguration speed_alert_configurations = 1;
|
||||
}
|
||||
|
||||
message SpeedAlertConfiguration {
|
||||
// Unix timestamp in seconds
|
||||
int64 end_timestamp_in_s = 1;
|
||||
// Speed in kilometers per hour
|
||||
int32 threshold_in_kph = 2;
|
||||
// threshold value in the users preferred unit
|
||||
string threshold_display_value = 3;
|
||||
}
|
||||
|
||||
message WeeklySettingsHeadUnitValue {
|
||||
// Array with 0 to 21 tupels of day (0..6, 0 = Monday, 1= Tuesday, ..) and departure time in min since midnight (0..1439)
|
||||
repeated WeeklySetting weekly_settings = 1;
|
||||
}
|
||||
|
||||
message WeeklySetting {
|
||||
int32 day = 1;
|
||||
int32 minutes_since_midnight = 2;
|
||||
}
|
||||
|
||||
message TemperaturePointsValue {
|
||||
// Array with 1 to 5 tupels of zone (frontLeft, frontRight, frontCenter, rearRight, rearLeft, rearCenter, rear2center)
|
||||
// and temperature in °C where 0 means maximum cooling (LOW) and 30 means maximum heating (HIGH)
|
||||
repeated TemperaturePoint temperature_points = 1;
|
||||
}
|
||||
|
||||
message TemperaturePoint {
|
||||
string zone = 1;
|
||||
double temperature = 2;
|
||||
string temperature_display_value = 3;
|
||||
}
|
||||
|
||||
message WeekdayTariffValue {
|
||||
// List of sampling points. Hint: Array will be empty in initial state. I. e.: rate and time will not be existent in initial state.
|
||||
repeated Tariff tariffs = 1;
|
||||
}
|
||||
|
||||
message WeekendTariffValue {
|
||||
// List of sampling points. Hint: Array will be empty in initial state. I. e.: rate and time will not be existent in initial state.
|
||||
repeated Tariff tariffs = 1;
|
||||
}
|
||||
|
||||
message Tariff {
|
||||
// 33 - off-peak, 44 - mid-peak, 66 - on-peak
|
||||
int32 rate = 1;
|
||||
// Seconds from midnight
|
||||
int32 time = 2;
|
||||
}
|
||||
|
||||
message StateOfChargeProfileValue {
|
||||
// Array with tupels of state of charge and time offset related to the timestamp of the attribute,
|
||||
// e.g. [{t, soc}, {t, soc}, .., {t, soc}] (every soc with value range 0..100, every timestamp in seconds, UTC)
|
||||
repeated StateOfCharge states_of_charge = 1;
|
||||
}
|
||||
|
||||
message StateOfCharge {
|
||||
// timestamp in seconds, UTC
|
||||
int64 timestamp_in_s = 1;
|
||||
|
||||
// soc with value range 0..100
|
||||
int32 state_of_charge = 2;
|
||||
}
|
||||
|
||||
// Sending direction: App <- BFF <- AppTwin
|
||||
message VEPUpdatesByVIN {
|
||||
|
||||
int32 sequence_number = 2;
|
||||
|
||||
// VIN -> Update
|
||||
map<string, VEPUpdate> updates = 1;
|
||||
}
|
||||
|
||||
// Sending direction: App <- BFF
|
||||
message DebugMessage {
|
||||
string message = 1;
|
||||
}
|
||||
|
||||
// Represents a status response from the
|
||||
// VVA backend for a given VIN and CIAM ID.
|
||||
message VehicleStatus {
|
||||
string vin = 1;
|
||||
map<string, VehicleAttributeStatus> attributes = 2;
|
||||
}
|
||||
|
||||
// message that is pushed from the vep status service
|
||||
// Sending direction: App <- BFF
|
||||
message PushMessage {
|
||||
reserved 7,8;
|
||||
string tracking_id = 5;
|
||||
oneof msg {
|
||||
VEPUpdate vepUpdate = 1;
|
||||
VEPUpdatesByVIN vepUpdates = 2;
|
||||
DebugMessage debugMessage = 3;
|
||||
ServiceStatusUpdatesByVIN service_status_updates = 9;
|
||||
ServiceStatusUpdate service_status_update = 13;
|
||||
UserDataUpdate user_data_update = 10;
|
||||
UserVehicleAuthChangedUpdate user_vehicle_auth_changed_update = 14;
|
||||
UserPictureUpdate user_picture_update = 11;
|
||||
UserPINUpdate user_pin_update = 12;
|
||||
VehicleUpdated vehicle_updated = 15;
|
||||
PreferredDealerChange preferred_dealer_change = 16;
|
||||
AppTwinCommandStatusUpdatesByVIN apptwin_command_status_updates_by_vin = 17;
|
||||
AppTwinPendingCommandsRequest apptwin_pending_command_request = 18;
|
||||
AssignedVehicles assigned_vehicles = 19;
|
||||
}
|
||||
}
|
||||
|
||||
// message type to track an event, e.g. a user interaction with content
|
||||
// Sending direction: App -> BFF
|
||||
message TrackingEvent {
|
||||
|
||||
// a unique id associated with this event
|
||||
string tracking_id = 1;
|
||||
|
||||
// the unix epoch time in nanoseconds when the event occurred
|
||||
int64 timestamp = 2;
|
||||
|
||||
// a unique identifier describing a single interaction or event
|
||||
string event_type = 3;
|
||||
|
||||
// additional meta data describing the event
|
||||
map<string, PayloadValue> payload = 4;
|
||||
}
|
||||
|
||||
message PayloadValue {
|
||||
oneof msg {
|
||||
string string_value = 1;
|
||||
int32 int_value = 2;
|
||||
bool bool_value = 3;
|
||||
double double_value = 4;
|
||||
}
|
||||
}
|
||||
|
||||
// acknowledge that the VEP updates of up to `sequenceNumber` have been received
|
||||
// Sending direction: App -> BFF -> AppTwin
|
||||
message AcknowledgeVEPRequest {
|
||||
// This message will be replaced by AcknowledgeVEPUpdatesByVIN
|
||||
option deprecated = true;
|
||||
|
||||
int32 sequence_number = 1;
|
||||
}
|
||||
|
||||
// acknowledge that the VEP updates by vin of up to `sequenceNumber` have been received
|
||||
// Sending direction: App -> BFF -> AppTwin
|
||||
// This message should replace the AcknowledgeVEPRequest
|
||||
message AcknowledgeVEPUpdatesByVIN {
|
||||
int32 sequence_number = 1;
|
||||
}
|
||||
|
||||
// the client can optionally send this message to reconfigure the ping interval
|
||||
// Sending direction: App -> BFF
|
||||
message ConfigurePingInterval {
|
||||
int32 ping_time_millis = 1;
|
||||
}
|
||||
|
||||
message AcknowledgeVehicleUpdated {
|
||||
int32 sequence_number = 1;
|
||||
}
|
||||
|
||||
message AcknowledgePreferredDealerChange {
|
||||
int32 sequence_number = 1;
|
||||
}
|
||||
|
||||
message VehicleUpdated {
|
||||
int32 sequence_number = 1;
|
||||
|
||||
string ciam_id = 2;
|
||||
|
||||
string vin = 3;
|
||||
|
||||
// When was the event emitted (milliseconds in Unix time)
|
||||
int64 emit_timestamp_in_ms = 10;
|
||||
}
|
||||
|
||||
message PreferredDealerChange {
|
||||
int32 sequence_number = 1;
|
||||
|
||||
string ciam_id = 2;
|
||||
|
||||
string vin = 3;
|
||||
|
||||
// When was the event emitted (milliseconds in Unix time)
|
||||
int64 emit_timestamp_in_ms = 10;
|
||||
}
|
156
bundles/org.openhab.binding.mercedesme/proto/vehicleapi.proto
Normal file
@ -0,0 +1,156 @@
|
||||
syntax = "proto3";
|
||||
package proto;
|
||||
|
||||
import "acp.proto";
|
||||
import "google/protobuf/struct.proto";
|
||||
//import "github.com/gogo/protobuf/gogoproto/gogo.proto";
|
||||
import "gogo.proto";
|
||||
|
||||
option (gogoproto.goproto_enum_prefix_all) = true;
|
||||
option java_package = "com.daimler.mbcarkit.proto";
|
||||
|
||||
// Sending direction: App -> BFF -> AppTwin
|
||||
message AcknowledgeAppTwinCommandStatusUpdatesByVIN {
|
||||
int32 sequence_number = 1;
|
||||
}
|
||||
|
||||
// Sending direction: App <- BFF <- AppTwin
|
||||
message AppTwinCommandStatusUpdatesByVIN {
|
||||
|
||||
int32 sequence_number = 1;
|
||||
|
||||
// VIN -> Update
|
||||
map<string, AppTwinCommandStatusUpdatesByPID> updates_by_vin = 2;
|
||||
}
|
||||
|
||||
// Sending direction: App <- BFF <- AppTwin as part of an AppTwinCommandStatusUpdatesByVIN
|
||||
message AppTwinCommandStatusUpdatesByPID {
|
||||
|
||||
string vin = 1;
|
||||
|
||||
// Process ID -> Status
|
||||
map<int64, AppTwinCommandStatus> updates_by_pid = 2;
|
||||
}
|
||||
|
||||
// Sending direction: App <- BFF <- AppTwin as part of an AppTwinCommandStatusUpdatesByPID
|
||||
message AppTwinCommandStatus {
|
||||
|
||||
// The remote vehicleAPI process id of the command.
|
||||
int64 process_id = 1;
|
||||
|
||||
// The id of the command with which the app created it. Only guaranteed to be
|
||||
// set on the first transmission to the app.
|
||||
string request_id = 2;
|
||||
|
||||
// The initial CommandStatus from the response of the vehicleAPI has a timestamp of
|
||||
// -1
|
||||
int64 timestamp_in_ms = 3;
|
||||
|
||||
// Potential ACP error if the command request could not be fulfilled
|
||||
repeated VehicleAPIError errors = 4;
|
||||
|
||||
// Potential timestamp until user cannot send login requests. Data in seconds
|
||||
// since Unix epoch
|
||||
int64 blocking_time_seconds = 5 [ deprecated = true ];
|
||||
|
||||
// Potential amount of failed pin attempts.
|
||||
int32 pin_attempts = 6 [ deprecated = true ];
|
||||
|
||||
// The type of command the AppTwinCommandStatus belongs to
|
||||
ACP.CommandType type = 7;
|
||||
|
||||
// The command state
|
||||
VehicleAPI.CommandState state = 8;
|
||||
}
|
||||
|
||||
// VehicleAPICommandPostResult is a message type that can be unmarshaled from a POST request against the vehicle API
|
||||
// for issuing commands.
|
||||
message VehicleAPICommandPostResult {
|
||||
|
||||
// The remote VVA process id of the command.
|
||||
int64 process_id = 1 [json_name = "processid"];
|
||||
|
||||
// Potential ACP error if the command request could not be fulfilled
|
||||
repeated VehicleAPIError errors = 2 [json_name = "errors"];
|
||||
|
||||
// The command state
|
||||
VehicleAPI.CommandState state = 3 [json_name = "state"];
|
||||
}
|
||||
|
||||
message VehicleAPICommandGetResult {
|
||||
// List of processes
|
||||
repeated VehicleAPICommandProcessStatus process = 1 [json_name = "process"];
|
||||
|
||||
// Number of enqueued commands in related command queue
|
||||
int32 queue_count = 2 [json_name = "queuecount"];
|
||||
|
||||
// Name of related command queue type
|
||||
VehicleAPI.QueueType queue_type = 3 [json_name = "queuetype"];
|
||||
}
|
||||
|
||||
message VehicleAPIDataGetResult {
|
||||
map<string, VehicleAPIAttributeStatus> data = 1;
|
||||
}
|
||||
|
||||
message VehicleAPIAttributeStatus {
|
||||
// Value of the attribute (can be anything)
|
||||
google.protobuf.Value value = 3 [json_name = "value"];
|
||||
// UTC timestamp in milliseconds
|
||||
int64 timestamp_in_ms = 2 [json_name = "ts"];
|
||||
// Status of the attribute
|
||||
VehicleAPI.AttributeStatus Status = 1 [json_name = "status"];
|
||||
}
|
||||
|
||||
message VehicleAPICommandProcessStatus {
|
||||
repeated VehicleAPIError errors = 1 [json_name = "errors"];
|
||||
|
||||
// GUID (RFC 4122)
|
||||
string instance_id = 2 [json_name = "instanceid"];
|
||||
|
||||
// Name of the command
|
||||
string name = 3 [json_name = "name"];
|
||||
|
||||
// Process ID
|
||||
int64 process_id = 4 [json_name = "processid"];
|
||||
|
||||
// The parameters with which the command was requested
|
||||
// google.protobuf.Value request_parameters = 5
|
||||
// [ json_name = "requestparameters" ];
|
||||
|
||||
// Response parameters as defined by the command
|
||||
google.protobuf.Value response_parameters = 6 [json_name = "responseparameters"];
|
||||
|
||||
// Current processing state
|
||||
VehicleAPI.CommandState state = 7 [json_name = "state"];
|
||||
|
||||
// UTC timestamp in seconds (ISO 9945)
|
||||
int64 timestamp_in_s = 8 [json_name = "timestamp"];
|
||||
|
||||
// Tracking ID. SHOULD be a GUID (RFC 4122)
|
||||
string tracking_id = 9 [json_name = "trackingid"];
|
||||
}
|
||||
|
||||
message VehicleAPIError {
|
||||
string code = 1 [json_name = "error-code"];
|
||||
string message = 2 [json_name = "error-message"];
|
||||
map<string, google.protobuf.Value> attributes = 3 [json_name = "attributes"];
|
||||
repeated VehicleAPIError sub_errors = 4 [json_name = "sub-errors"];
|
||||
}
|
||||
|
||||
// AppTwinPendingCommandsRequest is sent from the AppTwin to the app to ask for commands that the app has not yet
|
||||
// received a finished state for. This request MUST eventually be answered with AppTwinPendingCommandsResponse.
|
||||
message AppTwinPendingCommandsRequest {}
|
||||
|
||||
// AppTwinPendingCommandsResponse is sent from the app to the AppTwin to tell it the commands that haven't been
|
||||
// "resolved yet" (are not in a finished state). The delivery of this message to the AppTwin will trigger a command
|
||||
// actor that polls the state for the specified command type and PID.
|
||||
message AppTwinPendingCommandsResponse {
|
||||
repeated PendingCommand pending_commands = 1;
|
||||
}
|
||||
|
||||
message PendingCommand {
|
||||
string vin = 1;
|
||||
int64 process_id = 2;
|
||||
string request_id = 3;
|
||||
ACP.CommandType type = 4;
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
syntax = "proto3";
|
||||
package proto;
|
||||
|
||||
option java_package = "com.daimler.mbcarkit.proto";
|
||||
|
||||
message VINUpdate {
|
||||
repeated string addedVINs = 1;
|
||||
repeated string deletedVINs = 2;
|
||||
}
|
21
bundles/org.openhab.binding.mercedesme/src/3rdparty/LICENSE
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 MBition GmbH
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
5257
bundles/org.openhab.binding.mercedesme/src/3rdparty/java/com/daimler/mbcarkit/proto/Acp.java
vendored
Normal file
5548
bundles/org.openhab.binding.mercedesme/src/3rdparty/java/com/daimler/mbcarkit/proto/Client.java
vendored
Normal file
736
bundles/org.openhab.binding.mercedesme/src/3rdparty/java/com/daimler/mbcarkit/proto/Cluster.java
vendored
Normal file
@ -0,0 +1,736 @@
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: cluster.proto
|
||||
// Protobuf Java Version: 4.26.1
|
||||
|
||||
package com.daimler.mbcarkit.proto;
|
||||
|
||||
public final class Cluster {
|
||||
private Cluster() {}
|
||||
static {
|
||||
com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion(
|
||||
com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC,
|
||||
/* major= */ 4,
|
||||
/* minor= */ 26,
|
||||
/* patch= */ 1,
|
||||
/* suffix= */ "",
|
||||
Cluster.class.getName());
|
||||
}
|
||||
public static void registerAllExtensions(
|
||||
com.google.protobuf.ExtensionRegistryLite registry) {
|
||||
}
|
||||
|
||||
public static void registerAllExtensions(
|
||||
com.google.protobuf.ExtensionRegistry registry) {
|
||||
registerAllExtensions(
|
||||
(com.google.protobuf.ExtensionRegistryLite) registry);
|
||||
}
|
||||
/**
|
||||
* Protobuf enum {@code proto.MemberStatus}
|
||||
*/
|
||||
public enum MemberStatus
|
||||
implements com.google.protobuf.ProtocolMessageEnum {
|
||||
/**
|
||||
* <code>UNKNOWN_MEMBER_STATUS = 0;</code>
|
||||
*/
|
||||
UNKNOWN_MEMBER_STATUS(0),
|
||||
/**
|
||||
* <code>STARTING = 1;</code>
|
||||
*/
|
||||
STARTING(1),
|
||||
/**
|
||||
* <code>READY = 2;</code>
|
||||
*/
|
||||
READY(2),
|
||||
/**
|
||||
* <code>STOPPING = 3;</code>
|
||||
*/
|
||||
STOPPING(3),
|
||||
UNRECOGNIZED(-1),
|
||||
;
|
||||
|
||||
static {
|
||||
com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion(
|
||||
com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC,
|
||||
/* major= */ 4,
|
||||
/* minor= */ 26,
|
||||
/* patch= */ 1,
|
||||
/* suffix= */ "",
|
||||
MemberStatus.class.getName());
|
||||
}
|
||||
/**
|
||||
* <code>UNKNOWN_MEMBER_STATUS = 0;</code>
|
||||
*/
|
||||
public static final int UNKNOWN_MEMBER_STATUS_VALUE = 0;
|
||||
/**
|
||||
* <code>STARTING = 1;</code>
|
||||
*/
|
||||
public static final int STARTING_VALUE = 1;
|
||||
/**
|
||||
* <code>READY = 2;</code>
|
||||
*/
|
||||
public static final int READY_VALUE = 2;
|
||||
/**
|
||||
* <code>STOPPING = 3;</code>
|
||||
*/
|
||||
public static final int STOPPING_VALUE = 3;
|
||||
|
||||
|
||||
public final int getNumber() {
|
||||
if (this == UNRECOGNIZED) {
|
||||
throw new java.lang.IllegalArgumentException(
|
||||
"Can't get the number of an unknown enum value.");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param value The numeric wire value of the corresponding enum entry.
|
||||
* @return The enum associated with the given numeric wire value.
|
||||
* @deprecated Use {@link #forNumber(int)} instead.
|
||||
*/
|
||||
@java.lang.Deprecated
|
||||
public static MemberStatus valueOf(int value) {
|
||||
return forNumber(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param value The numeric wire value of the corresponding enum entry.
|
||||
* @return The enum associated with the given numeric wire value.
|
||||
*/
|
||||
public static MemberStatus forNumber(int value) {
|
||||
switch (value) {
|
||||
case 0: return UNKNOWN_MEMBER_STATUS;
|
||||
case 1: return STARTING;
|
||||
case 2: return READY;
|
||||
case 3: return STOPPING;
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static com.google.protobuf.Internal.EnumLiteMap<MemberStatus>
|
||||
internalGetValueMap() {
|
||||
return internalValueMap;
|
||||
}
|
||||
private static final com.google.protobuf.Internal.EnumLiteMap<
|
||||
MemberStatus> internalValueMap =
|
||||
new com.google.protobuf.Internal.EnumLiteMap<MemberStatus>() {
|
||||
public MemberStatus findValueByNumber(int number) {
|
||||
return MemberStatus.forNumber(number);
|
||||
}
|
||||
};
|
||||
|
||||
public final com.google.protobuf.Descriptors.EnumValueDescriptor
|
||||
getValueDescriptor() {
|
||||
if (this == UNRECOGNIZED) {
|
||||
throw new java.lang.IllegalStateException(
|
||||
"Can't get the descriptor of an unrecognized enum value.");
|
||||
}
|
||||
return getDescriptor().getValues().get(ordinal());
|
||||
}
|
||||
public final com.google.protobuf.Descriptors.EnumDescriptor
|
||||
getDescriptorForType() {
|
||||
return getDescriptor();
|
||||
}
|
||||
public static final com.google.protobuf.Descriptors.EnumDescriptor
|
||||
getDescriptor() {
|
||||
return com.daimler.mbcarkit.proto.Cluster.getDescriptor().getEnumTypes().get(0);
|
||||
}
|
||||
|
||||
private static final MemberStatus[] VALUES = values();
|
||||
|
||||
public static MemberStatus valueOf(
|
||||
com.google.protobuf.Descriptors.EnumValueDescriptor desc) {
|
||||
if (desc.getType() != getDescriptor()) {
|
||||
throw new java.lang.IllegalArgumentException(
|
||||
"EnumValueDescriptor is not for this type.");
|
||||
}
|
||||
if (desc.getIndex() == -1) {
|
||||
return UNRECOGNIZED;
|
||||
}
|
||||
return VALUES[desc.getIndex()];
|
||||
}
|
||||
|
||||
private final int value;
|
||||
|
||||
private MemberStatus(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
// @@protoc_insertion_point(enum_scope:proto.MemberStatus)
|
||||
}
|
||||
|
||||
public interface AppTwinMemberStatusValueOrBuilder extends
|
||||
// @@protoc_insertion_point(interface_extends:proto.AppTwinMemberStatusValue)
|
||||
com.google.protobuf.MessageOrBuilder {
|
||||
|
||||
/**
|
||||
* <code>.proto.MemberStatus status = 1;</code>
|
||||
* @return The enum numeric value on the wire for status.
|
||||
*/
|
||||
int getStatusValue();
|
||||
/**
|
||||
* <code>.proto.MemberStatus status = 1;</code>
|
||||
* @return The status.
|
||||
*/
|
||||
com.daimler.mbcarkit.proto.Cluster.MemberStatus getStatus();
|
||||
|
||||
/**
|
||||
* <code>uint32 apptwin_count = 2;</code>
|
||||
* @return The apptwinCount.
|
||||
*/
|
||||
int getApptwinCount();
|
||||
}
|
||||
/**
|
||||
* Protobuf type {@code proto.AppTwinMemberStatusValue}
|
||||
*/
|
||||
public static final class AppTwinMemberStatusValue extends
|
||||
com.google.protobuf.GeneratedMessage implements
|
||||
// @@protoc_insertion_point(message_implements:proto.AppTwinMemberStatusValue)
|
||||
AppTwinMemberStatusValueOrBuilder {
|
||||
private static final long serialVersionUID = 0L;
|
||||
static {
|
||||
com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion(
|
||||
com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC,
|
||||
/* major= */ 4,
|
||||
/* minor= */ 26,
|
||||
/* patch= */ 1,
|
||||
/* suffix= */ "",
|
||||
AppTwinMemberStatusValue.class.getName());
|
||||
}
|
||||
// Use AppTwinMemberStatusValue.newBuilder() to construct.
|
||||
private AppTwinMemberStatusValue(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
|
||||
super(builder);
|
||||
}
|
||||
private AppTwinMemberStatusValue() {
|
||||
status_ = 0;
|
||||
}
|
||||
|
||||
public static final com.google.protobuf.Descriptors.Descriptor
|
||||
getDescriptor() {
|
||||
return com.daimler.mbcarkit.proto.Cluster.internal_static_proto_AppTwinMemberStatusValue_descriptor;
|
||||
}
|
||||
|
||||
@java.lang.Override
|
||||
protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
|
||||
internalGetFieldAccessorTable() {
|
||||
return com.daimler.mbcarkit.proto.Cluster.internal_static_proto_AppTwinMemberStatusValue_fieldAccessorTable
|
||||
.ensureFieldAccessorsInitialized(
|
||||
com.daimler.mbcarkit.proto.Cluster.AppTwinMemberStatusValue.class, com.daimler.mbcarkit.proto.Cluster.AppTwinMemberStatusValue.Builder.class);
|
||||
}
|
||||
|
||||
public static final int STATUS_FIELD_NUMBER = 1;
|
||||
private int status_ = 0;
|
||||
/**
|
||||
* <code>.proto.MemberStatus status = 1;</code>
|
||||
* @return The enum numeric value on the wire for status.
|
||||
*/
|
||||
@java.lang.Override public int getStatusValue() {
|
||||
return status_;
|
||||
}
|
||||
/**
|
||||
* <code>.proto.MemberStatus status = 1;</code>
|
||||
* @return The status.
|
||||
*/
|
||||
@java.lang.Override public com.daimler.mbcarkit.proto.Cluster.MemberStatus getStatus() {
|
||||
com.daimler.mbcarkit.proto.Cluster.MemberStatus result = com.daimler.mbcarkit.proto.Cluster.MemberStatus.forNumber(status_);
|
||||
return result == null ? com.daimler.mbcarkit.proto.Cluster.MemberStatus.UNRECOGNIZED : result;
|
||||
}
|
||||
|
||||
public static final int APPTWIN_COUNT_FIELD_NUMBER = 2;
|
||||
private int apptwinCount_ = 0;
|
||||
/**
|
||||
* <code>uint32 apptwin_count = 2;</code>
|
||||
* @return The apptwinCount.
|
||||
*/
|
||||
@java.lang.Override
|
||||
public int getApptwinCount() {
|
||||
return apptwinCount_;
|
||||
}
|
||||
|
||||
private byte memoizedIsInitialized = -1;
|
||||
@java.lang.Override
|
||||
public final boolean isInitialized() {
|
||||
byte isInitialized = memoizedIsInitialized;
|
||||
if (isInitialized == 1) return true;
|
||||
if (isInitialized == 0) return false;
|
||||
|
||||
memoizedIsInitialized = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
@java.lang.Override
|
||||
public void writeTo(com.google.protobuf.CodedOutputStream output)
|
||||
throws java.io.IOException {
|
||||
if (status_ != com.daimler.mbcarkit.proto.Cluster.MemberStatus.UNKNOWN_MEMBER_STATUS.getNumber()) {
|
||||
output.writeEnum(1, status_);
|
||||
}
|
||||
if (apptwinCount_ != 0) {
|
||||
output.writeUInt32(2, apptwinCount_);
|
||||
}
|
||||
getUnknownFields().writeTo(output);
|
||||
}
|
||||
|
||||
@java.lang.Override
|
||||
public int getSerializedSize() {
|
||||
int size = memoizedSize;
|
||||
if (size != -1) return size;
|
||||
|
||||
size = 0;
|
||||
if (status_ != com.daimler.mbcarkit.proto.Cluster.MemberStatus.UNKNOWN_MEMBER_STATUS.getNumber()) {
|
||||
size += com.google.protobuf.CodedOutputStream
|
||||
.computeEnumSize(1, status_);
|
||||
}
|
||||
if (apptwinCount_ != 0) {
|
||||
size += com.google.protobuf.CodedOutputStream
|
||||
.computeUInt32Size(2, apptwinCount_);
|
||||
}
|
||||
size += getUnknownFields().getSerializedSize();
|
||||
memoizedSize = size;
|
||||
return size;
|
||||
}
|
||||
|
||||
@java.lang.Override
|
||||
public boolean equals(final java.lang.Object obj) {
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
if (!(obj instanceof com.daimler.mbcarkit.proto.Cluster.AppTwinMemberStatusValue)) {
|
||||
return super.equals(obj);
|
||||
}
|
||||
com.daimler.mbcarkit.proto.Cluster.AppTwinMemberStatusValue other = (com.daimler.mbcarkit.proto.Cluster.AppTwinMemberStatusValue) obj;
|
||||
|
||||
if (status_ != other.status_) return false;
|
||||
if (getApptwinCount()
|
||||
!= other.getApptwinCount()) return false;
|
||||
if (!getUnknownFields().equals(other.getUnknownFields())) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@java.lang.Override
|
||||
public int hashCode() {
|
||||
if (memoizedHashCode != 0) {
|
||||
return memoizedHashCode;
|
||||
}
|
||||
int hash = 41;
|
||||
hash = (19 * hash) + getDescriptor().hashCode();
|
||||
hash = (37 * hash) + STATUS_FIELD_NUMBER;
|
||||
hash = (53 * hash) + status_;
|
||||
hash = (37 * hash) + APPTWIN_COUNT_FIELD_NUMBER;
|
||||
hash = (53 * hash) + getApptwinCount();
|
||||
hash = (29 * hash) + getUnknownFields().hashCode();
|
||||
memoizedHashCode = hash;
|
||||
return hash;
|
||||
}
|
||||
|
||||
public static com.daimler.mbcarkit.proto.Cluster.AppTwinMemberStatusValue parseFrom(
|
||||
java.nio.ByteBuffer data)
|
||||
throws com.google.protobuf.InvalidProtocolBufferException {
|
||||
return PARSER.parseFrom(data);
|
||||
}
|
||||
public static com.daimler.mbcarkit.proto.Cluster.AppTwinMemberStatusValue parseFrom(
|
||||
java.nio.ByteBuffer data,
|
||||
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
|
||||
throws com.google.protobuf.InvalidProtocolBufferException {
|
||||
return PARSER.parseFrom(data, extensionRegistry);
|
||||
}
|
||||
public static com.daimler.mbcarkit.proto.Cluster.AppTwinMemberStatusValue parseFrom(
|
||||
com.google.protobuf.ByteString data)
|
||||
throws com.google.protobuf.InvalidProtocolBufferException {
|
||||
return PARSER.parseFrom(data);
|
||||
}
|
||||
public static com.daimler.mbcarkit.proto.Cluster.AppTwinMemberStatusValue parseFrom(
|
||||
com.google.protobuf.ByteString data,
|
||||
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
|
||||
throws com.google.protobuf.InvalidProtocolBufferException {
|
||||
return PARSER.parseFrom(data, extensionRegistry);
|
||||
}
|
||||
public static com.daimler.mbcarkit.proto.Cluster.AppTwinMemberStatusValue parseFrom(byte[] data)
|
||||
throws com.google.protobuf.InvalidProtocolBufferException {
|
||||
return PARSER.parseFrom(data);
|
||||
}
|
||||
public static com.daimler.mbcarkit.proto.Cluster.AppTwinMemberStatusValue parseFrom(
|
||||
byte[] data,
|
||||
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
|
||||
throws com.google.protobuf.InvalidProtocolBufferException {
|
||||
return PARSER.parseFrom(data, extensionRegistry);
|
||||
}
|
||||
public static com.daimler.mbcarkit.proto.Cluster.AppTwinMemberStatusValue parseFrom(java.io.InputStream input)
|
||||
throws java.io.IOException {
|
||||
return com.google.protobuf.GeneratedMessage
|
||||
.parseWithIOException(PARSER, input);
|
||||
}
|
||||
public static com.daimler.mbcarkit.proto.Cluster.AppTwinMemberStatusValue parseFrom(
|
||||
java.io.InputStream input,
|
||||
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
|
||||
throws java.io.IOException {
|
||||
return com.google.protobuf.GeneratedMessage
|
||||
.parseWithIOException(PARSER, input, extensionRegistry);
|
||||
}
|
||||
|
||||
public static com.daimler.mbcarkit.proto.Cluster.AppTwinMemberStatusValue parseDelimitedFrom(java.io.InputStream input)
|
||||
throws java.io.IOException {
|
||||
return com.google.protobuf.GeneratedMessage
|
||||
.parseDelimitedWithIOException(PARSER, input);
|
||||
}
|
||||
|
||||
public static com.daimler.mbcarkit.proto.Cluster.AppTwinMemberStatusValue parseDelimitedFrom(
|
||||
java.io.InputStream input,
|
||||
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
|
||||
throws java.io.IOException {
|
||||
return com.google.protobuf.GeneratedMessage
|
||||
.parseDelimitedWithIOException(PARSER, input, extensionRegistry);
|
||||
}
|
||||
public static com.daimler.mbcarkit.proto.Cluster.AppTwinMemberStatusValue parseFrom(
|
||||
com.google.protobuf.CodedInputStream input)
|
||||
throws java.io.IOException {
|
||||
return com.google.protobuf.GeneratedMessage
|
||||
.parseWithIOException(PARSER, input);
|
||||
}
|
||||
public static com.daimler.mbcarkit.proto.Cluster.AppTwinMemberStatusValue parseFrom(
|
||||
com.google.protobuf.CodedInputStream input,
|
||||
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
|
||||
throws java.io.IOException {
|
||||
return com.google.protobuf.GeneratedMessage
|
||||
.parseWithIOException(PARSER, input, extensionRegistry);
|
||||
}
|
||||
|
||||
@java.lang.Override
|
||||
public Builder newBuilderForType() { return newBuilder(); }
|
||||
public static Builder newBuilder() {
|
||||
return DEFAULT_INSTANCE.toBuilder();
|
||||
}
|
||||
public static Builder newBuilder(com.daimler.mbcarkit.proto.Cluster.AppTwinMemberStatusValue prototype) {
|
||||
return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
|
||||
}
|
||||
@java.lang.Override
|
||||
public Builder toBuilder() {
|
||||
return this == DEFAULT_INSTANCE
|
||||
? new Builder() : new Builder().mergeFrom(this);
|
||||
}
|
||||
|
||||
@java.lang.Override
|
||||
protected Builder newBuilderForType(
|
||||
com.google.protobuf.GeneratedMessage.BuilderParent parent) {
|
||||
Builder builder = new Builder(parent);
|
||||
return builder;
|
||||
}
|
||||
/**
|
||||
* Protobuf type {@code proto.AppTwinMemberStatusValue}
|
||||
*/
|
||||
public static final class Builder extends
|
||||
com.google.protobuf.GeneratedMessage.Builder<Builder> implements
|
||||
// @@protoc_insertion_point(builder_implements:proto.AppTwinMemberStatusValue)
|
||||
com.daimler.mbcarkit.proto.Cluster.AppTwinMemberStatusValueOrBuilder {
|
||||
public static final com.google.protobuf.Descriptors.Descriptor
|
||||
getDescriptor() {
|
||||
return com.daimler.mbcarkit.proto.Cluster.internal_static_proto_AppTwinMemberStatusValue_descriptor;
|
||||
}
|
||||
|
||||
@java.lang.Override
|
||||
protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
|
||||
internalGetFieldAccessorTable() {
|
||||
return com.daimler.mbcarkit.proto.Cluster.internal_static_proto_AppTwinMemberStatusValue_fieldAccessorTable
|
||||
.ensureFieldAccessorsInitialized(
|
||||
com.daimler.mbcarkit.proto.Cluster.AppTwinMemberStatusValue.class, com.daimler.mbcarkit.proto.Cluster.AppTwinMemberStatusValue.Builder.class);
|
||||
}
|
||||
|
||||
// Construct using com.daimler.mbcarkit.proto.Cluster.AppTwinMemberStatusValue.newBuilder()
|
||||
private Builder() {
|
||||
|
||||
}
|
||||
|
||||
private Builder(
|
||||
com.google.protobuf.GeneratedMessage.BuilderParent parent) {
|
||||
super(parent);
|
||||
|
||||
}
|
||||
@java.lang.Override
|
||||
public Builder clear() {
|
||||
super.clear();
|
||||
bitField0_ = 0;
|
||||
status_ = 0;
|
||||
apptwinCount_ = 0;
|
||||
return this;
|
||||
}
|
||||
|
||||
@java.lang.Override
|
||||
public com.google.protobuf.Descriptors.Descriptor
|
||||
getDescriptorForType() {
|
||||
return com.daimler.mbcarkit.proto.Cluster.internal_static_proto_AppTwinMemberStatusValue_descriptor;
|
||||
}
|
||||
|
||||
@java.lang.Override
|
||||
public com.daimler.mbcarkit.proto.Cluster.AppTwinMemberStatusValue getDefaultInstanceForType() {
|
||||
return com.daimler.mbcarkit.proto.Cluster.AppTwinMemberStatusValue.getDefaultInstance();
|
||||
}
|
||||
|
||||
@java.lang.Override
|
||||
public com.daimler.mbcarkit.proto.Cluster.AppTwinMemberStatusValue build() {
|
||||
com.daimler.mbcarkit.proto.Cluster.AppTwinMemberStatusValue result = buildPartial();
|
||||
if (!result.isInitialized()) {
|
||||
throw newUninitializedMessageException(result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@java.lang.Override
|
||||
public com.daimler.mbcarkit.proto.Cluster.AppTwinMemberStatusValue buildPartial() {
|
||||
com.daimler.mbcarkit.proto.Cluster.AppTwinMemberStatusValue result = new com.daimler.mbcarkit.proto.Cluster.AppTwinMemberStatusValue(this);
|
||||
if (bitField0_ != 0) { buildPartial0(result); }
|
||||
onBuilt();
|
||||
return result;
|
||||
}
|
||||
|
||||
private void buildPartial0(com.daimler.mbcarkit.proto.Cluster.AppTwinMemberStatusValue result) {
|
||||
int from_bitField0_ = bitField0_;
|
||||
if (((from_bitField0_ & 0x00000001) != 0)) {
|
||||
result.status_ = status_;
|
||||
}
|
||||
if (((from_bitField0_ & 0x00000002) != 0)) {
|
||||
result.apptwinCount_ = apptwinCount_;
|
||||
}
|
||||
}
|
||||
|
||||
@java.lang.Override
|
||||
public Builder mergeFrom(com.google.protobuf.Message other) {
|
||||
if (other instanceof com.daimler.mbcarkit.proto.Cluster.AppTwinMemberStatusValue) {
|
||||
return mergeFrom((com.daimler.mbcarkit.proto.Cluster.AppTwinMemberStatusValue)other);
|
||||
} else {
|
||||
super.mergeFrom(other);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public Builder mergeFrom(com.daimler.mbcarkit.proto.Cluster.AppTwinMemberStatusValue other) {
|
||||
if (other == com.daimler.mbcarkit.proto.Cluster.AppTwinMemberStatusValue.getDefaultInstance()) return this;
|
||||
if (other.status_ != 0) {
|
||||
setStatusValue(other.getStatusValue());
|
||||
}
|
||||
if (other.getApptwinCount() != 0) {
|
||||
setApptwinCount(other.getApptwinCount());
|
||||
}
|
||||
this.mergeUnknownFields(other.getUnknownFields());
|
||||
onChanged();
|
||||
return this;
|
||||
}
|
||||
|
||||
@java.lang.Override
|
||||
public final boolean isInitialized() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@java.lang.Override
|
||||
public Builder mergeFrom(
|
||||
com.google.protobuf.CodedInputStream input,
|
||||
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
|
||||
throws java.io.IOException {
|
||||
if (extensionRegistry == null) {
|
||||
throw new java.lang.NullPointerException();
|
||||
}
|
||||
try {
|
||||
boolean done = false;
|
||||
while (!done) {
|
||||
int tag = input.readTag();
|
||||
switch (tag) {
|
||||
case 0:
|
||||
done = true;
|
||||
break;
|
||||
case 8: {
|
||||
status_ = input.readEnum();
|
||||
bitField0_ |= 0x00000001;
|
||||
break;
|
||||
} // case 8
|
||||
case 16: {
|
||||
apptwinCount_ = input.readUInt32();
|
||||
bitField0_ |= 0x00000002;
|
||||
break;
|
||||
} // case 16
|
||||
default: {
|
||||
if (!super.parseUnknownField(input, extensionRegistry, tag)) {
|
||||
done = true; // was an endgroup tag
|
||||
}
|
||||
break;
|
||||
} // default:
|
||||
} // switch (tag)
|
||||
} // while (!done)
|
||||
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
|
||||
throw e.unwrapIOException();
|
||||
} finally {
|
||||
onChanged();
|
||||
} // finally
|
||||
return this;
|
||||
}
|
||||
private int bitField0_;
|
||||
|
||||
private int status_ = 0;
|
||||
/**
|
||||
* <code>.proto.MemberStatus status = 1;</code>
|
||||
* @return The enum numeric value on the wire for status.
|
||||
*/
|
||||
@java.lang.Override public int getStatusValue() {
|
||||
return status_;
|
||||
}
|
||||
/**
|
||||
* <code>.proto.MemberStatus status = 1;</code>
|
||||
* @param value The enum numeric value on the wire for status to set.
|
||||
* @return This builder for chaining.
|
||||
*/
|
||||
public Builder setStatusValue(int value) {
|
||||
status_ = value;
|
||||
bitField0_ |= 0x00000001;
|
||||
onChanged();
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* <code>.proto.MemberStatus status = 1;</code>
|
||||
* @return The status.
|
||||
*/
|
||||
@java.lang.Override
|
||||
public com.daimler.mbcarkit.proto.Cluster.MemberStatus getStatus() {
|
||||
com.daimler.mbcarkit.proto.Cluster.MemberStatus result = com.daimler.mbcarkit.proto.Cluster.MemberStatus.forNumber(status_);
|
||||
return result == null ? com.daimler.mbcarkit.proto.Cluster.MemberStatus.UNRECOGNIZED : result;
|
||||
}
|
||||
/**
|
||||
* <code>.proto.MemberStatus status = 1;</code>
|
||||
* @param value The status to set.
|
||||
* @return This builder for chaining.
|
||||
*/
|
||||
public Builder setStatus(com.daimler.mbcarkit.proto.Cluster.MemberStatus value) {
|
||||
if (value == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
bitField0_ |= 0x00000001;
|
||||
status_ = value.getNumber();
|
||||
onChanged();
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* <code>.proto.MemberStatus status = 1;</code>
|
||||
* @return This builder for chaining.
|
||||
*/
|
||||
public Builder clearStatus() {
|
||||
bitField0_ = (bitField0_ & ~0x00000001);
|
||||
status_ = 0;
|
||||
onChanged();
|
||||
return this;
|
||||
}
|
||||
|
||||
private int apptwinCount_ ;
|
||||
/**
|
||||
* <code>uint32 apptwin_count = 2;</code>
|
||||
* @return The apptwinCount.
|
||||
*/
|
||||
@java.lang.Override
|
||||
public int getApptwinCount() {
|
||||
return apptwinCount_;
|
||||
}
|
||||
/**
|
||||
* <code>uint32 apptwin_count = 2;</code>
|
||||
* @param value The apptwinCount to set.
|
||||
* @return This builder for chaining.
|
||||
*/
|
||||
public Builder setApptwinCount(int value) {
|
||||
|
||||
apptwinCount_ = value;
|
||||
bitField0_ |= 0x00000002;
|
||||
onChanged();
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* <code>uint32 apptwin_count = 2;</code>
|
||||
* @return This builder for chaining.
|
||||
*/
|
||||
public Builder clearApptwinCount() {
|
||||
bitField0_ = (bitField0_ & ~0x00000002);
|
||||
apptwinCount_ = 0;
|
||||
onChanged();
|
||||
return this;
|
||||
}
|
||||
|
||||
// @@protoc_insertion_point(builder_scope:proto.AppTwinMemberStatusValue)
|
||||
}
|
||||
|
||||
// @@protoc_insertion_point(class_scope:proto.AppTwinMemberStatusValue)
|
||||
private static final com.daimler.mbcarkit.proto.Cluster.AppTwinMemberStatusValue DEFAULT_INSTANCE;
|
||||
static {
|
||||
DEFAULT_INSTANCE = new com.daimler.mbcarkit.proto.Cluster.AppTwinMemberStatusValue();
|
||||
}
|
||||
|
||||
public static com.daimler.mbcarkit.proto.Cluster.AppTwinMemberStatusValue getDefaultInstance() {
|
||||
return DEFAULT_INSTANCE;
|
||||
}
|
||||
|
||||
private static final com.google.protobuf.Parser<AppTwinMemberStatusValue>
|
||||
PARSER = new com.google.protobuf.AbstractParser<AppTwinMemberStatusValue>() {
|
||||
@java.lang.Override
|
||||
public AppTwinMemberStatusValue parsePartialFrom(
|
||||
com.google.protobuf.CodedInputStream input,
|
||||
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
|
||||
throws com.google.protobuf.InvalidProtocolBufferException {
|
||||
Builder builder = newBuilder();
|
||||
try {
|
||||
builder.mergeFrom(input, extensionRegistry);
|
||||
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
|
||||
throw e.setUnfinishedMessage(builder.buildPartial());
|
||||
} catch (com.google.protobuf.UninitializedMessageException e) {
|
||||
throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial());
|
||||
} catch (java.io.IOException e) {
|
||||
throw new com.google.protobuf.InvalidProtocolBufferException(e)
|
||||
.setUnfinishedMessage(builder.buildPartial());
|
||||
}
|
||||
return builder.buildPartial();
|
||||
}
|
||||
};
|
||||
|
||||
public static com.google.protobuf.Parser<AppTwinMemberStatusValue> parser() {
|
||||
return PARSER;
|
||||
}
|
||||
|
||||
@java.lang.Override
|
||||
public com.google.protobuf.Parser<AppTwinMemberStatusValue> getParserForType() {
|
||||
return PARSER;
|
||||
}
|
||||
|
||||
@java.lang.Override
|
||||
public com.daimler.mbcarkit.proto.Cluster.AppTwinMemberStatusValue getDefaultInstanceForType() {
|
||||
return DEFAULT_INSTANCE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static final com.google.protobuf.Descriptors.Descriptor
|
||||
internal_static_proto_AppTwinMemberStatusValue_descriptor;
|
||||
private static final
|
||||
com.google.protobuf.GeneratedMessage.FieldAccessorTable
|
||||
internal_static_proto_AppTwinMemberStatusValue_fieldAccessorTable;
|
||||
|
||||
public static com.google.protobuf.Descriptors.FileDescriptor
|
||||
getDescriptor() {
|
||||
return descriptor;
|
||||
}
|
||||
private static com.google.protobuf.Descriptors.FileDescriptor
|
||||
descriptor;
|
||||
static {
|
||||
java.lang.String[] descriptorData = {
|
||||
"\n\rcluster.proto\022\005proto\"V\n\030AppTwinMemberS" +
|
||||
"tatusValue\022#\n\006status\030\001 \001(\0162\023.proto.Membe" +
|
||||
"rStatus\022\025\n\rapptwin_count\030\002 \001(\r*P\n\014Member" +
|
||||
"Status\022\031\n\025UNKNOWN_MEMBER_STATUS\020\000\022\014\n\010STA" +
|
||||
"RTING\020\001\022\t\n\005READY\020\002\022\014\n\010STOPPING\020\003B\034\n\032com." +
|
||||
"daimler.mbcarkit.protob\006proto3"
|
||||
};
|
||||
descriptor = com.google.protobuf.Descriptors.FileDescriptor
|
||||
.internalBuildGeneratedFileFrom(descriptorData,
|
||||
new com.google.protobuf.Descriptors.FileDescriptor[] {
|
||||
});
|
||||
internal_static_proto_AppTwinMemberStatusValue_descriptor =
|
||||
getDescriptor().getMessageTypes().get(0);
|
||||
internal_static_proto_AppTwinMemberStatusValue_fieldAccessorTable = new
|
||||
com.google.protobuf.GeneratedMessage.FieldAccessorTable(
|
||||
internal_static_proto_AppTwinMemberStatusValue_descriptor,
|
||||
new java.lang.String[] { "Status", "ApptwinCount", });
|
||||
descriptor.resolveAllFeaturesImmutable();
|
||||
}
|
||||
|
||||
// @@protoc_insertion_point(outer_class_scope)
|
||||
}
|
1684
bundles/org.openhab.binding.mercedesme/src/3rdparty/java/com/daimler/mbcarkit/proto/Eventpush.java
vendored
Normal file
11252
bundles/org.openhab.binding.mercedesme/src/3rdparty/java/com/daimler/mbcarkit/proto/Protos.java
vendored
Normal file
14181
bundles/org.openhab.binding.mercedesme/src/3rdparty/java/com/daimler/mbcarkit/proto/UserEvents.java
vendored
Normal file
47071
bundles/org.openhab.binding.mercedesme/src/3rdparty/java/com/daimler/mbcarkit/proto/VehicleCommands.java
vendored
Normal file
34774
bundles/org.openhab.binding.mercedesme/src/3rdparty/java/com/daimler/mbcarkit/proto/VehicleEvents.java
vendored
Normal file
13223
bundles/org.openhab.binding.mercedesme/src/3rdparty/java/com/daimler/mbcarkit/proto/Vehicleapi.java
vendored
Normal file
849
bundles/org.openhab.binding.mercedesme/src/3rdparty/java/com/daimler/mbcarkit/proto/VinEvents.java
vendored
Normal file
@ -0,0 +1,849 @@
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: vin-events.proto
|
||||
// Protobuf Java Version: 4.26.1
|
||||
|
||||
package com.daimler.mbcarkit.proto;
|
||||
|
||||
public final class VinEvents {
|
||||
private VinEvents() {}
|
||||
static {
|
||||
com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion(
|
||||
com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC,
|
||||
/* major= */ 4,
|
||||
/* minor= */ 26,
|
||||
/* patch= */ 1,
|
||||
/* suffix= */ "",
|
||||
VinEvents.class.getName());
|
||||
}
|
||||
public static void registerAllExtensions(
|
||||
com.google.protobuf.ExtensionRegistryLite registry) {
|
||||
}
|
||||
|
||||
public static void registerAllExtensions(
|
||||
com.google.protobuf.ExtensionRegistry registry) {
|
||||
registerAllExtensions(
|
||||
(com.google.protobuf.ExtensionRegistryLite) registry);
|
||||
}
|
||||
public interface VINUpdateOrBuilder extends
|
||||
// @@protoc_insertion_point(interface_extends:proto.VINUpdate)
|
||||
com.google.protobuf.MessageOrBuilder {
|
||||
|
||||
/**
|
||||
* <code>repeated string addedVINs = 1;</code>
|
||||
* @return A list containing the addedVINs.
|
||||
*/
|
||||
java.util.List<java.lang.String>
|
||||
getAddedVINsList();
|
||||
/**
|
||||
* <code>repeated string addedVINs = 1;</code>
|
||||
* @return The count of addedVINs.
|
||||
*/
|
||||
int getAddedVINsCount();
|
||||
/**
|
||||
* <code>repeated string addedVINs = 1;</code>
|
||||
* @param index The index of the element to return.
|
||||
* @return The addedVINs at the given index.
|
||||
*/
|
||||
java.lang.String getAddedVINs(int index);
|
||||
/**
|
||||
* <code>repeated string addedVINs = 1;</code>
|
||||
* @param index The index of the value to return.
|
||||
* @return The bytes of the addedVINs at the given index.
|
||||
*/
|
||||
com.google.protobuf.ByteString
|
||||
getAddedVINsBytes(int index);
|
||||
|
||||
/**
|
||||
* <code>repeated string deletedVINs = 2;</code>
|
||||
* @return A list containing the deletedVINs.
|
||||
*/
|
||||
java.util.List<java.lang.String>
|
||||
getDeletedVINsList();
|
||||
/**
|
||||
* <code>repeated string deletedVINs = 2;</code>
|
||||
* @return The count of deletedVINs.
|
||||
*/
|
||||
int getDeletedVINsCount();
|
||||
/**
|
||||
* <code>repeated string deletedVINs = 2;</code>
|
||||
* @param index The index of the element to return.
|
||||
* @return The deletedVINs at the given index.
|
||||
*/
|
||||
java.lang.String getDeletedVINs(int index);
|
||||
/**
|
||||
* <code>repeated string deletedVINs = 2;</code>
|
||||
* @param index The index of the value to return.
|
||||
* @return The bytes of the deletedVINs at the given index.
|
||||
*/
|
||||
com.google.protobuf.ByteString
|
||||
getDeletedVINsBytes(int index);
|
||||
}
|
||||
/**
|
||||
* Protobuf type {@code proto.VINUpdate}
|
||||
*/
|
||||
public static final class VINUpdate extends
|
||||
com.google.protobuf.GeneratedMessage implements
|
||||
// @@protoc_insertion_point(message_implements:proto.VINUpdate)
|
||||
VINUpdateOrBuilder {
|
||||
private static final long serialVersionUID = 0L;
|
||||
static {
|
||||
com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion(
|
||||
com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC,
|
||||
/* major= */ 4,
|
||||
/* minor= */ 26,
|
||||
/* patch= */ 1,
|
||||
/* suffix= */ "",
|
||||
VINUpdate.class.getName());
|
||||
}
|
||||
// Use VINUpdate.newBuilder() to construct.
|
||||
private VINUpdate(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
|
||||
super(builder);
|
||||
}
|
||||
private VINUpdate() {
|
||||
addedVINs_ =
|
||||
com.google.protobuf.LazyStringArrayList.emptyList();
|
||||
deletedVINs_ =
|
||||
com.google.protobuf.LazyStringArrayList.emptyList();
|
||||
}
|
||||
|
||||
public static final com.google.protobuf.Descriptors.Descriptor
|
||||
getDescriptor() {
|
||||
return com.daimler.mbcarkit.proto.VinEvents.internal_static_proto_VINUpdate_descriptor;
|
||||
}
|
||||
|
||||
@java.lang.Override
|
||||
protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
|
||||
internalGetFieldAccessorTable() {
|
||||
return com.daimler.mbcarkit.proto.VinEvents.internal_static_proto_VINUpdate_fieldAccessorTable
|
||||
.ensureFieldAccessorsInitialized(
|
||||
com.daimler.mbcarkit.proto.VinEvents.VINUpdate.class, com.daimler.mbcarkit.proto.VinEvents.VINUpdate.Builder.class);
|
||||
}
|
||||
|
||||
public static final int ADDEDVINS_FIELD_NUMBER = 1;
|
||||
@SuppressWarnings("serial")
|
||||
private com.google.protobuf.LazyStringArrayList addedVINs_ =
|
||||
com.google.protobuf.LazyStringArrayList.emptyList();
|
||||
/**
|
||||
* <code>repeated string addedVINs = 1;</code>
|
||||
* @return A list containing the addedVINs.
|
||||
*/
|
||||
public com.google.protobuf.ProtocolStringList
|
||||
getAddedVINsList() {
|
||||
return addedVINs_;
|
||||
}
|
||||
/**
|
||||
* <code>repeated string addedVINs = 1;</code>
|
||||
* @return The count of addedVINs.
|
||||
*/
|
||||
public int getAddedVINsCount() {
|
||||
return addedVINs_.size();
|
||||
}
|
||||
/**
|
||||
* <code>repeated string addedVINs = 1;</code>
|
||||
* @param index The index of the element to return.
|
||||
* @return The addedVINs at the given index.
|
||||
*/
|
||||
public java.lang.String getAddedVINs(int index) {
|
||||
return addedVINs_.get(index);
|
||||
}
|
||||
/**
|
||||
* <code>repeated string addedVINs = 1;</code>
|
||||
* @param index The index of the value to return.
|
||||
* @return The bytes of the addedVINs at the given index.
|
||||
*/
|
||||
public com.google.protobuf.ByteString
|
||||
getAddedVINsBytes(int index) {
|
||||
return addedVINs_.getByteString(index);
|
||||
}
|
||||
|
||||
public static final int DELETEDVINS_FIELD_NUMBER = 2;
|
||||
@SuppressWarnings("serial")
|
||||
private com.google.protobuf.LazyStringArrayList deletedVINs_ =
|
||||
com.google.protobuf.LazyStringArrayList.emptyList();
|
||||
/**
|
||||
* <code>repeated string deletedVINs = 2;</code>
|
||||
* @return A list containing the deletedVINs.
|
||||
*/
|
||||
public com.google.protobuf.ProtocolStringList
|
||||
getDeletedVINsList() {
|
||||
return deletedVINs_;
|
||||
}
|
||||
/**
|
||||
* <code>repeated string deletedVINs = 2;</code>
|
||||
* @return The count of deletedVINs.
|
||||
*/
|
||||
public int getDeletedVINsCount() {
|
||||
return deletedVINs_.size();
|
||||
}
|
||||
/**
|
||||
* <code>repeated string deletedVINs = 2;</code>
|
||||
* @param index The index of the element to return.
|
||||
* @return The deletedVINs at the given index.
|
||||
*/
|
||||
public java.lang.String getDeletedVINs(int index) {
|
||||
return deletedVINs_.get(index);
|
||||
}
|
||||
/**
|
||||
* <code>repeated string deletedVINs = 2;</code>
|
||||
* @param index The index of the value to return.
|
||||
* @return The bytes of the deletedVINs at the given index.
|
||||
*/
|
||||
public com.google.protobuf.ByteString
|
||||
getDeletedVINsBytes(int index) {
|
||||
return deletedVINs_.getByteString(index);
|
||||
}
|
||||
|
||||
private byte memoizedIsInitialized = -1;
|
||||
@java.lang.Override
|
||||
public final boolean isInitialized() {
|
||||
byte isInitialized = memoizedIsInitialized;
|
||||
if (isInitialized == 1) return true;
|
||||
if (isInitialized == 0) return false;
|
||||
|
||||
memoizedIsInitialized = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
@java.lang.Override
|
||||
public void writeTo(com.google.protobuf.CodedOutputStream output)
|
||||
throws java.io.IOException {
|
||||
for (int i = 0; i < addedVINs_.size(); i++) {
|
||||
com.google.protobuf.GeneratedMessage.writeString(output, 1, addedVINs_.getRaw(i));
|
||||
}
|
||||
for (int i = 0; i < deletedVINs_.size(); i++) {
|
||||
com.google.protobuf.GeneratedMessage.writeString(output, 2, deletedVINs_.getRaw(i));
|
||||
}
|
||||
getUnknownFields().writeTo(output);
|
||||
}
|
||||
|
||||
@java.lang.Override
|
||||
public int getSerializedSize() {
|
||||
int size = memoizedSize;
|
||||
if (size != -1) return size;
|
||||
|
||||
size = 0;
|
||||
{
|
||||
int dataSize = 0;
|
||||
for (int i = 0; i < addedVINs_.size(); i++) {
|
||||
dataSize += computeStringSizeNoTag(addedVINs_.getRaw(i));
|
||||
}
|
||||
size += dataSize;
|
||||
size += 1 * getAddedVINsList().size();
|
||||
}
|
||||
{
|
||||
int dataSize = 0;
|
||||
for (int i = 0; i < deletedVINs_.size(); i++) {
|
||||
dataSize += computeStringSizeNoTag(deletedVINs_.getRaw(i));
|
||||
}
|
||||
size += dataSize;
|
||||
size += 1 * getDeletedVINsList().size();
|
||||
}
|
||||
size += getUnknownFields().getSerializedSize();
|
||||
memoizedSize = size;
|
||||
return size;
|
||||
}
|
||||
|
||||
@java.lang.Override
|
||||
public boolean equals(final java.lang.Object obj) {
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
if (!(obj instanceof com.daimler.mbcarkit.proto.VinEvents.VINUpdate)) {
|
||||
return super.equals(obj);
|
||||
}
|
||||
com.daimler.mbcarkit.proto.VinEvents.VINUpdate other = (com.daimler.mbcarkit.proto.VinEvents.VINUpdate) obj;
|
||||
|
||||
if (!getAddedVINsList()
|
||||
.equals(other.getAddedVINsList())) return false;
|
||||
if (!getDeletedVINsList()
|
||||
.equals(other.getDeletedVINsList())) return false;
|
||||
if (!getUnknownFields().equals(other.getUnknownFields())) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@java.lang.Override
|
||||
public int hashCode() {
|
||||
if (memoizedHashCode != 0) {
|
||||
return memoizedHashCode;
|
||||
}
|
||||
int hash = 41;
|
||||
hash = (19 * hash) + getDescriptor().hashCode();
|
||||
if (getAddedVINsCount() > 0) {
|
||||
hash = (37 * hash) + ADDEDVINS_FIELD_NUMBER;
|
||||
hash = (53 * hash) + getAddedVINsList().hashCode();
|
||||
}
|
||||
if (getDeletedVINsCount() > 0) {
|
||||
hash = (37 * hash) + DELETEDVINS_FIELD_NUMBER;
|
||||
hash = (53 * hash) + getDeletedVINsList().hashCode();
|
||||
}
|
||||
hash = (29 * hash) + getUnknownFields().hashCode();
|
||||
memoizedHashCode = hash;
|
||||
return hash;
|
||||
}
|
||||
|
||||
public static com.daimler.mbcarkit.proto.VinEvents.VINUpdate parseFrom(
|
||||
java.nio.ByteBuffer data)
|
||||
throws com.google.protobuf.InvalidProtocolBufferException {
|
||||
return PARSER.parseFrom(data);
|
||||
}
|
||||
public static com.daimler.mbcarkit.proto.VinEvents.VINUpdate parseFrom(
|
||||
java.nio.ByteBuffer data,
|
||||
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
|
||||
throws com.google.protobuf.InvalidProtocolBufferException {
|
||||
return PARSER.parseFrom(data, extensionRegistry);
|
||||
}
|
||||
public static com.daimler.mbcarkit.proto.VinEvents.VINUpdate parseFrom(
|
||||
com.google.protobuf.ByteString data)
|
||||
throws com.google.protobuf.InvalidProtocolBufferException {
|
||||
return PARSER.parseFrom(data);
|
||||
}
|
||||
public static com.daimler.mbcarkit.proto.VinEvents.VINUpdate parseFrom(
|
||||
com.google.protobuf.ByteString data,
|
||||
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
|
||||
throws com.google.protobuf.InvalidProtocolBufferException {
|
||||
return PARSER.parseFrom(data, extensionRegistry);
|
||||
}
|
||||
public static com.daimler.mbcarkit.proto.VinEvents.VINUpdate parseFrom(byte[] data)
|
||||
throws com.google.protobuf.InvalidProtocolBufferException {
|
||||
return PARSER.parseFrom(data);
|
||||
}
|
||||
public static com.daimler.mbcarkit.proto.VinEvents.VINUpdate parseFrom(
|
||||
byte[] data,
|
||||
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
|
||||
throws com.google.protobuf.InvalidProtocolBufferException {
|
||||
return PARSER.parseFrom(data, extensionRegistry);
|
||||
}
|
||||
public static com.daimler.mbcarkit.proto.VinEvents.VINUpdate parseFrom(java.io.InputStream input)
|
||||
throws java.io.IOException {
|
||||
return com.google.protobuf.GeneratedMessage
|
||||
.parseWithIOException(PARSER, input);
|
||||
}
|
||||
public static com.daimler.mbcarkit.proto.VinEvents.VINUpdate parseFrom(
|
||||
java.io.InputStream input,
|
||||
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
|
||||
throws java.io.IOException {
|
||||
return com.google.protobuf.GeneratedMessage
|
||||
.parseWithIOException(PARSER, input, extensionRegistry);
|
||||
}
|
||||
|
||||
public static com.daimler.mbcarkit.proto.VinEvents.VINUpdate parseDelimitedFrom(java.io.InputStream input)
|
||||
throws java.io.IOException {
|
||||
return com.google.protobuf.GeneratedMessage
|
||||
.parseDelimitedWithIOException(PARSER, input);
|
||||
}
|
||||
|
||||
public static com.daimler.mbcarkit.proto.VinEvents.VINUpdate parseDelimitedFrom(
|
||||
java.io.InputStream input,
|
||||
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
|
||||
throws java.io.IOException {
|
||||
return com.google.protobuf.GeneratedMessage
|
||||
.parseDelimitedWithIOException(PARSER, input, extensionRegistry);
|
||||
}
|
||||
public static com.daimler.mbcarkit.proto.VinEvents.VINUpdate parseFrom(
|
||||
com.google.protobuf.CodedInputStream input)
|
||||
throws java.io.IOException {
|
||||
return com.google.protobuf.GeneratedMessage
|
||||
.parseWithIOException(PARSER, input);
|
||||
}
|
||||
public static com.daimler.mbcarkit.proto.VinEvents.VINUpdate parseFrom(
|
||||
com.google.protobuf.CodedInputStream input,
|
||||
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
|
||||
throws java.io.IOException {
|
||||
return com.google.protobuf.GeneratedMessage
|
||||
.parseWithIOException(PARSER, input, extensionRegistry);
|
||||
}
|
||||
|
||||
@java.lang.Override
|
||||
public Builder newBuilderForType() { return newBuilder(); }
|
||||
public static Builder newBuilder() {
|
||||
return DEFAULT_INSTANCE.toBuilder();
|
||||
}
|
||||
public static Builder newBuilder(com.daimler.mbcarkit.proto.VinEvents.VINUpdate prototype) {
|
||||
return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
|
||||
}
|
||||
@java.lang.Override
|
||||
public Builder toBuilder() {
|
||||
return this == DEFAULT_INSTANCE
|
||||
? new Builder() : new Builder().mergeFrom(this);
|
||||
}
|
||||
|
||||
@java.lang.Override
|
||||
protected Builder newBuilderForType(
|
||||
com.google.protobuf.GeneratedMessage.BuilderParent parent) {
|
||||
Builder builder = new Builder(parent);
|
||||
return builder;
|
||||
}
|
||||
/**
|
||||
* Protobuf type {@code proto.VINUpdate}
|
||||
*/
|
||||
public static final class Builder extends
|
||||
com.google.protobuf.GeneratedMessage.Builder<Builder> implements
|
||||
// @@protoc_insertion_point(builder_implements:proto.VINUpdate)
|
||||
com.daimler.mbcarkit.proto.VinEvents.VINUpdateOrBuilder {
|
||||
public static final com.google.protobuf.Descriptors.Descriptor
|
||||
getDescriptor() {
|
||||
return com.daimler.mbcarkit.proto.VinEvents.internal_static_proto_VINUpdate_descriptor;
|
||||
}
|
||||
|
||||
@java.lang.Override
|
||||
protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
|
||||
internalGetFieldAccessorTable() {
|
||||
return com.daimler.mbcarkit.proto.VinEvents.internal_static_proto_VINUpdate_fieldAccessorTable
|
||||
.ensureFieldAccessorsInitialized(
|
||||
com.daimler.mbcarkit.proto.VinEvents.VINUpdate.class, com.daimler.mbcarkit.proto.VinEvents.VINUpdate.Builder.class);
|
||||
}
|
||||
|
||||
// Construct using com.daimler.mbcarkit.proto.VinEvents.VINUpdate.newBuilder()
|
||||
private Builder() {
|
||||
|
||||
}
|
||||
|
||||
private Builder(
|
||||
com.google.protobuf.GeneratedMessage.BuilderParent parent) {
|
||||
super(parent);
|
||||
|
||||
}
|
||||
@java.lang.Override
|
||||
public Builder clear() {
|
||||
super.clear();
|
||||
bitField0_ = 0;
|
||||
addedVINs_ =
|
||||
com.google.protobuf.LazyStringArrayList.emptyList();
|
||||
deletedVINs_ =
|
||||
com.google.protobuf.LazyStringArrayList.emptyList();
|
||||
return this;
|
||||
}
|
||||
|
||||
@java.lang.Override
|
||||
public com.google.protobuf.Descriptors.Descriptor
|
||||
getDescriptorForType() {
|
||||
return com.daimler.mbcarkit.proto.VinEvents.internal_static_proto_VINUpdate_descriptor;
|
||||
}
|
||||
|
||||
@java.lang.Override
|
||||
public com.daimler.mbcarkit.proto.VinEvents.VINUpdate getDefaultInstanceForType() {
|
||||
return com.daimler.mbcarkit.proto.VinEvents.VINUpdate.getDefaultInstance();
|
||||
}
|
||||
|
||||
@java.lang.Override
|
||||
public com.daimler.mbcarkit.proto.VinEvents.VINUpdate build() {
|
||||
com.daimler.mbcarkit.proto.VinEvents.VINUpdate result = buildPartial();
|
||||
if (!result.isInitialized()) {
|
||||
throw newUninitializedMessageException(result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@java.lang.Override
|
||||
public com.daimler.mbcarkit.proto.VinEvents.VINUpdate buildPartial() {
|
||||
com.daimler.mbcarkit.proto.VinEvents.VINUpdate result = new com.daimler.mbcarkit.proto.VinEvents.VINUpdate(this);
|
||||
if (bitField0_ != 0) { buildPartial0(result); }
|
||||
onBuilt();
|
||||
return result;
|
||||
}
|
||||
|
||||
private void buildPartial0(com.daimler.mbcarkit.proto.VinEvents.VINUpdate result) {
|
||||
int from_bitField0_ = bitField0_;
|
||||
if (((from_bitField0_ & 0x00000001) != 0)) {
|
||||
addedVINs_.makeImmutable();
|
||||
result.addedVINs_ = addedVINs_;
|
||||
}
|
||||
if (((from_bitField0_ & 0x00000002) != 0)) {
|
||||
deletedVINs_.makeImmutable();
|
||||
result.deletedVINs_ = deletedVINs_;
|
||||
}
|
||||
}
|
||||
|
||||
@java.lang.Override
|
||||
public Builder mergeFrom(com.google.protobuf.Message other) {
|
||||
if (other instanceof com.daimler.mbcarkit.proto.VinEvents.VINUpdate) {
|
||||
return mergeFrom((com.daimler.mbcarkit.proto.VinEvents.VINUpdate)other);
|
||||
} else {
|
||||
super.mergeFrom(other);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public Builder mergeFrom(com.daimler.mbcarkit.proto.VinEvents.VINUpdate other) {
|
||||
if (other == com.daimler.mbcarkit.proto.VinEvents.VINUpdate.getDefaultInstance()) return this;
|
||||
if (!other.addedVINs_.isEmpty()) {
|
||||
if (addedVINs_.isEmpty()) {
|
||||
addedVINs_ = other.addedVINs_;
|
||||
bitField0_ |= 0x00000001;
|
||||
} else {
|
||||
ensureAddedVINsIsMutable();
|
||||
addedVINs_.addAll(other.addedVINs_);
|
||||
}
|
||||
onChanged();
|
||||
}
|
||||
if (!other.deletedVINs_.isEmpty()) {
|
||||
if (deletedVINs_.isEmpty()) {
|
||||
deletedVINs_ = other.deletedVINs_;
|
||||
bitField0_ |= 0x00000002;
|
||||
} else {
|
||||
ensureDeletedVINsIsMutable();
|
||||
deletedVINs_.addAll(other.deletedVINs_);
|
||||
}
|
||||
onChanged();
|
||||
}
|
||||
this.mergeUnknownFields(other.getUnknownFields());
|
||||
onChanged();
|
||||
return this;
|
||||
}
|
||||
|
||||
@java.lang.Override
|
||||
public final boolean isInitialized() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@java.lang.Override
|
||||
public Builder mergeFrom(
|
||||
com.google.protobuf.CodedInputStream input,
|
||||
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
|
||||
throws java.io.IOException {
|
||||
if (extensionRegistry == null) {
|
||||
throw new java.lang.NullPointerException();
|
||||
}
|
||||
try {
|
||||
boolean done = false;
|
||||
while (!done) {
|
||||
int tag = input.readTag();
|
||||
switch (tag) {
|
||||
case 0:
|
||||
done = true;
|
||||
break;
|
||||
case 10: {
|
||||
java.lang.String s = input.readStringRequireUtf8();
|
||||
ensureAddedVINsIsMutable();
|
||||
addedVINs_.add(s);
|
||||
break;
|
||||
} // case 10
|
||||
case 18: {
|
||||
java.lang.String s = input.readStringRequireUtf8();
|
||||
ensureDeletedVINsIsMutable();
|
||||
deletedVINs_.add(s);
|
||||
break;
|
||||
} // case 18
|
||||
default: {
|
||||
if (!super.parseUnknownField(input, extensionRegistry, tag)) {
|
||||
done = true; // was an endgroup tag
|
||||
}
|
||||
break;
|
||||
} // default:
|
||||
} // switch (tag)
|
||||
} // while (!done)
|
||||
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
|
||||
throw e.unwrapIOException();
|
||||
} finally {
|
||||
onChanged();
|
||||
} // finally
|
||||
return this;
|
||||
}
|
||||
private int bitField0_;
|
||||
|
||||
private com.google.protobuf.LazyStringArrayList addedVINs_ =
|
||||
com.google.protobuf.LazyStringArrayList.emptyList();
|
||||
private void ensureAddedVINsIsMutable() {
|
||||
if (!addedVINs_.isModifiable()) {
|
||||
addedVINs_ = new com.google.protobuf.LazyStringArrayList(addedVINs_);
|
||||
}
|
||||
bitField0_ |= 0x00000001;
|
||||
}
|
||||
/**
|
||||
* <code>repeated string addedVINs = 1;</code>
|
||||
* @return A list containing the addedVINs.
|
||||
*/
|
||||
public com.google.protobuf.ProtocolStringList
|
||||
getAddedVINsList() {
|
||||
addedVINs_.makeImmutable();
|
||||
return addedVINs_;
|
||||
}
|
||||
/**
|
||||
* <code>repeated string addedVINs = 1;</code>
|
||||
* @return The count of addedVINs.
|
||||
*/
|
||||
public int getAddedVINsCount() {
|
||||
return addedVINs_.size();
|
||||
}
|
||||
/**
|
||||
* <code>repeated string addedVINs = 1;</code>
|
||||
* @param index The index of the element to return.
|
||||
* @return The addedVINs at the given index.
|
||||
*/
|
||||
public java.lang.String getAddedVINs(int index) {
|
||||
return addedVINs_.get(index);
|
||||
}
|
||||
/**
|
||||
* <code>repeated string addedVINs = 1;</code>
|
||||
* @param index The index of the value to return.
|
||||
* @return The bytes of the addedVINs at the given index.
|
||||
*/
|
||||
public com.google.protobuf.ByteString
|
||||
getAddedVINsBytes(int index) {
|
||||
return addedVINs_.getByteString(index);
|
||||
}
|
||||
/**
|
||||
* <code>repeated string addedVINs = 1;</code>
|
||||
* @param index The index to set the value at.
|
||||
* @param value The addedVINs to set.
|
||||
* @return This builder for chaining.
|
||||
*/
|
||||
public Builder setAddedVINs(
|
||||
int index, java.lang.String value) {
|
||||
if (value == null) { throw new NullPointerException(); }
|
||||
ensureAddedVINsIsMutable();
|
||||
addedVINs_.set(index, value);
|
||||
bitField0_ |= 0x00000001;
|
||||
onChanged();
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* <code>repeated string addedVINs = 1;</code>
|
||||
* @param value The addedVINs to add.
|
||||
* @return This builder for chaining.
|
||||
*/
|
||||
public Builder addAddedVINs(
|
||||
java.lang.String value) {
|
||||
if (value == null) { throw new NullPointerException(); }
|
||||
ensureAddedVINsIsMutable();
|
||||
addedVINs_.add(value);
|
||||
bitField0_ |= 0x00000001;
|
||||
onChanged();
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* <code>repeated string addedVINs = 1;</code>
|
||||
* @param values The addedVINs to add.
|
||||
* @return This builder for chaining.
|
||||
*/
|
||||
public Builder addAllAddedVINs(
|
||||
java.lang.Iterable<java.lang.String> values) {
|
||||
ensureAddedVINsIsMutable();
|
||||
com.google.protobuf.AbstractMessageLite.Builder.addAll(
|
||||
values, addedVINs_);
|
||||
bitField0_ |= 0x00000001;
|
||||
onChanged();
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* <code>repeated string addedVINs = 1;</code>
|
||||
* @return This builder for chaining.
|
||||
*/
|
||||
public Builder clearAddedVINs() {
|
||||
addedVINs_ =
|
||||
com.google.protobuf.LazyStringArrayList.emptyList();
|
||||
bitField0_ = (bitField0_ & ~0x00000001);;
|
||||
onChanged();
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* <code>repeated string addedVINs = 1;</code>
|
||||
* @param value The bytes of the addedVINs to add.
|
||||
* @return This builder for chaining.
|
||||
*/
|
||||
public Builder addAddedVINsBytes(
|
||||
com.google.protobuf.ByteString value) {
|
||||
if (value == null) { throw new NullPointerException(); }
|
||||
checkByteStringIsUtf8(value);
|
||||
ensureAddedVINsIsMutable();
|
||||
addedVINs_.add(value);
|
||||
bitField0_ |= 0x00000001;
|
||||
onChanged();
|
||||
return this;
|
||||
}
|
||||
|
||||
private com.google.protobuf.LazyStringArrayList deletedVINs_ =
|
||||
com.google.protobuf.LazyStringArrayList.emptyList();
|
||||
private void ensureDeletedVINsIsMutable() {
|
||||
if (!deletedVINs_.isModifiable()) {
|
||||
deletedVINs_ = new com.google.protobuf.LazyStringArrayList(deletedVINs_);
|
||||
}
|
||||
bitField0_ |= 0x00000002;
|
||||
}
|
||||
/**
|
||||
* <code>repeated string deletedVINs = 2;</code>
|
||||
* @return A list containing the deletedVINs.
|
||||
*/
|
||||
public com.google.protobuf.ProtocolStringList
|
||||
getDeletedVINsList() {
|
||||
deletedVINs_.makeImmutable();
|
||||
return deletedVINs_;
|
||||
}
|
||||
/**
|
||||
* <code>repeated string deletedVINs = 2;</code>
|
||||
* @return The count of deletedVINs.
|
||||
*/
|
||||
public int getDeletedVINsCount() {
|
||||
return deletedVINs_.size();
|
||||
}
|
||||
/**
|
||||
* <code>repeated string deletedVINs = 2;</code>
|
||||
* @param index The index of the element to return.
|
||||
* @return The deletedVINs at the given index.
|
||||
*/
|
||||
public java.lang.String getDeletedVINs(int index) {
|
||||
return deletedVINs_.get(index);
|
||||
}
|
||||
/**
|
||||
* <code>repeated string deletedVINs = 2;</code>
|
||||
* @param index The index of the value to return.
|
||||
* @return The bytes of the deletedVINs at the given index.
|
||||
*/
|
||||
public com.google.protobuf.ByteString
|
||||
getDeletedVINsBytes(int index) {
|
||||
return deletedVINs_.getByteString(index);
|
||||
}
|
||||
/**
|
||||
* <code>repeated string deletedVINs = 2;</code>
|
||||
* @param index The index to set the value at.
|
||||
* @param value The deletedVINs to set.
|
||||
* @return This builder for chaining.
|
||||
*/
|
||||
public Builder setDeletedVINs(
|
||||
int index, java.lang.String value) {
|
||||
if (value == null) { throw new NullPointerException(); }
|
||||
ensureDeletedVINsIsMutable();
|
||||
deletedVINs_.set(index, value);
|
||||
bitField0_ |= 0x00000002;
|
||||
onChanged();
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* <code>repeated string deletedVINs = 2;</code>
|
||||
* @param value The deletedVINs to add.
|
||||
* @return This builder for chaining.
|
||||
*/
|
||||
public Builder addDeletedVINs(
|
||||
java.lang.String value) {
|
||||
if (value == null) { throw new NullPointerException(); }
|
||||
ensureDeletedVINsIsMutable();
|
||||
deletedVINs_.add(value);
|
||||
bitField0_ |= 0x00000002;
|
||||
onChanged();
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* <code>repeated string deletedVINs = 2;</code>
|
||||
* @param values The deletedVINs to add.
|
||||
* @return This builder for chaining.
|
||||
*/
|
||||
public Builder addAllDeletedVINs(
|
||||
java.lang.Iterable<java.lang.String> values) {
|
||||
ensureDeletedVINsIsMutable();
|
||||
com.google.protobuf.AbstractMessageLite.Builder.addAll(
|
||||
values, deletedVINs_);
|
||||
bitField0_ |= 0x00000002;
|
||||
onChanged();
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* <code>repeated string deletedVINs = 2;</code>
|
||||
* @return This builder for chaining.
|
||||
*/
|
||||
public Builder clearDeletedVINs() {
|
||||
deletedVINs_ =
|
||||
com.google.protobuf.LazyStringArrayList.emptyList();
|
||||
bitField0_ = (bitField0_ & ~0x00000002);;
|
||||
onChanged();
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* <code>repeated string deletedVINs = 2;</code>
|
||||
* @param value The bytes of the deletedVINs to add.
|
||||
* @return This builder for chaining.
|
||||
*/
|
||||
public Builder addDeletedVINsBytes(
|
||||
com.google.protobuf.ByteString value) {
|
||||
if (value == null) { throw new NullPointerException(); }
|
||||
checkByteStringIsUtf8(value);
|
||||
ensureDeletedVINsIsMutable();
|
||||
deletedVINs_.add(value);
|
||||
bitField0_ |= 0x00000002;
|
||||
onChanged();
|
||||
return this;
|
||||
}
|
||||
|
||||
// @@protoc_insertion_point(builder_scope:proto.VINUpdate)
|
||||
}
|
||||
|
||||
// @@protoc_insertion_point(class_scope:proto.VINUpdate)
|
||||
private static final com.daimler.mbcarkit.proto.VinEvents.VINUpdate DEFAULT_INSTANCE;
|
||||
static {
|
||||
DEFAULT_INSTANCE = new com.daimler.mbcarkit.proto.VinEvents.VINUpdate();
|
||||
}
|
||||
|
||||
public static com.daimler.mbcarkit.proto.VinEvents.VINUpdate getDefaultInstance() {
|
||||
return DEFAULT_INSTANCE;
|
||||
}
|
||||
|
||||
private static final com.google.protobuf.Parser<VINUpdate>
|
||||
PARSER = new com.google.protobuf.AbstractParser<VINUpdate>() {
|
||||
@java.lang.Override
|
||||
public VINUpdate parsePartialFrom(
|
||||
com.google.protobuf.CodedInputStream input,
|
||||
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
|
||||
throws com.google.protobuf.InvalidProtocolBufferException {
|
||||
Builder builder = newBuilder();
|
||||
try {
|
||||
builder.mergeFrom(input, extensionRegistry);
|
||||
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
|
||||
throw e.setUnfinishedMessage(builder.buildPartial());
|
||||
} catch (com.google.protobuf.UninitializedMessageException e) {
|
||||
throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial());
|
||||
} catch (java.io.IOException e) {
|
||||
throw new com.google.protobuf.InvalidProtocolBufferException(e)
|
||||
.setUnfinishedMessage(builder.buildPartial());
|
||||
}
|
||||
return builder.buildPartial();
|
||||
}
|
||||
};
|
||||
|
||||
public static com.google.protobuf.Parser<VINUpdate> parser() {
|
||||
return PARSER;
|
||||
}
|
||||
|
||||
@java.lang.Override
|
||||
public com.google.protobuf.Parser<VINUpdate> getParserForType() {
|
||||
return PARSER;
|
||||
}
|
||||
|
||||
@java.lang.Override
|
||||
public com.daimler.mbcarkit.proto.VinEvents.VINUpdate getDefaultInstanceForType() {
|
||||
return DEFAULT_INSTANCE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static final com.google.protobuf.Descriptors.Descriptor
|
||||
internal_static_proto_VINUpdate_descriptor;
|
||||
private static final
|
||||
com.google.protobuf.GeneratedMessage.FieldAccessorTable
|
||||
internal_static_proto_VINUpdate_fieldAccessorTable;
|
||||
|
||||
public static com.google.protobuf.Descriptors.FileDescriptor
|
||||
getDescriptor() {
|
||||
return descriptor;
|
||||
}
|
||||
private static com.google.protobuf.Descriptors.FileDescriptor
|
||||
descriptor;
|
||||
static {
|
||||
java.lang.String[] descriptorData = {
|
||||
"\n\020vin-events.proto\022\005proto\"3\n\tVINUpdate\022\021" +
|
||||
"\n\taddedVINs\030\001 \003(\t\022\023\n\013deletedVINs\030\002 \003(\tB\034" +
|
||||
"\n\032com.daimler.mbcarkit.protob\006proto3"
|
||||
};
|
||||
descriptor = com.google.protobuf.Descriptors.FileDescriptor
|
||||
.internalBuildGeneratedFileFrom(descriptorData,
|
||||
new com.google.protobuf.Descriptors.FileDescriptor[] {
|
||||
});
|
||||
internal_static_proto_VINUpdate_descriptor =
|
||||
getDescriptor().getMessageTypes().get(0);
|
||||
internal_static_proto_VINUpdate_fieldAccessorTable = new
|
||||
com.google.protobuf.GeneratedMessage.FieldAccessorTable(
|
||||
internal_static_proto_VINUpdate_descriptor,
|
||||
new java.lang.String[] { "AddedVINs", "DeletedVINs", });
|
||||
descriptor.resolveAllFeaturesImmutable();
|
||||
}
|
||||
|
||||
// @@protoc_insertion_point(outer_class_scope)
|
||||
}
|
1146
bundles/org.openhab.binding.mercedesme/src/3rdparty/java/com/google/protobuf/GoGoProtos.java
vendored
Normal file
@ -12,22 +12,32 @@
|
||||
*/
|
||||
package org.openhab.binding.mercedesme.internal;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import javax.measure.Unit;
|
||||
import javax.measure.quantity.Energy;
|
||||
import javax.measure.quantity.Length;
|
||||
import javax.measure.quantity.Power;
|
||||
import javax.measure.quantity.Pressure;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.library.unit.MetricPrefix;
|
||||
import org.openhab.core.library.unit.SIUnits;
|
||||
import org.openhab.core.library.unit.Units;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
|
||||
/**
|
||||
* The {@link Constants} class defines common constants, which are
|
||||
* {@link Constants} defines common constants, which are
|
||||
* used across the whole binding.
|
||||
*
|
||||
* @author Bernd Weymann - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class Constants {
|
||||
public static final String BINDING_VERSION = "oh-release";
|
||||
public static final String BINDING_ID = "mercedesme";
|
||||
|
||||
public static final String COMBUSTION = "combustion";
|
||||
@ -40,60 +50,282 @@ public class Constants {
|
||||
public static final ThingTypeUID THING_TYPE_HYBRID = new ThingTypeUID(BINDING_ID, HYBRID);
|
||||
public static final ThingTypeUID THING_TYPE_BEV = new ThingTypeUID(BINDING_ID, BEV);
|
||||
|
||||
public static final String GROUP_RANGE = "range";
|
||||
public static final int REQUEST_TIMEOUT_MS = 10_000;
|
||||
|
||||
public static final Set<ThingTypeUID> DISCOVERABLE_DEVICE_TYPE_UIDS = Collections
|
||||
.unmodifiableSet(Stream.of(THING_TYPE_COMB, THING_TYPE_HYBRID, THING_TYPE_BEV).collect(Collectors.toSet()));
|
||||
|
||||
public static final String MB_KEY_TIRE_SENSOR_AVAILABLE = "tireSensorAvailable";
|
||||
public static final String MB_KEY_CHARGE_COUPLER_DC_LOCK_STATUS = "chargeCouplerDCLockStatus";
|
||||
public static final String MB_KEY_CHARGE_COUPLER_DC_STATUS = "chargeCouplerDCStatus";
|
||||
public static final String MB_KEY_CHARGE_COUPLER_AC_STATUS = "chargeCouplerACStatus";
|
||||
public static final String MB_KEY_CHARGE_FLAP_DC_STATUS = "chargeFlapDCStatus";
|
||||
public static final String MB_KEY_SERVICEINTERVALDAYS = "serviceintervaldays";
|
||||
public static final String MB_KEY_TIREWARNINGSRDK = "tirewarningsrdk";
|
||||
public static final String MB_KEY_STARTER_BATTERY_STATE = "starterBatteryState";
|
||||
public static final String MB_KEY_FLIP_WINDOW_STATUS = "flipWindowStatus";
|
||||
public static final String MB_KEY_WINDOW_STATUS_REAR_BLIND = "windowStatusRearBlind";
|
||||
public static final String MB_KEY_WINDOW_STATUS_REAR_LEFT_BLIND = "windowStatusRearLeftBlind";
|
||||
public static final String MB_KEY_WINDOW_STATUS_REAR_RIGHT_BLIND = "windowStatusRearRightBlind";
|
||||
public static final String MB_KEY_WINDOWSTATUSREARRIGHT = "windowstatusrearright";
|
||||
public static final String MB_KEY_WINDOWSTATUSREARLEFT = "windowstatusrearleft";
|
||||
public static final String MB_KEY_WINDOWSTATUSFRONTRIGHT = "windowstatusfrontright";
|
||||
public static final String MB_KEY_WINDOWSTATUSFRONTLEFT = "windowstatusfrontleft";
|
||||
public static final String MB_KEY_ROOFTOPSTATUS = "rooftopstatus";
|
||||
public static final String MB_KEY_SUNROOF_STATUS_REAR_BLIND = "sunroofStatusRearBlind";
|
||||
public static final String MB_KEY_SUNROOF_STATUS_FRONT_BLIND = "sunroofStatusFrontBlind";
|
||||
public static final String MB_KEY_SUNROOFSTATUS = "sunroofstatus";
|
||||
public static final String MB_KEY_IGNITIONSTATE = "ignitionstate";
|
||||
public static final String MB_KEY_DOOR_STATUS_OVERALL = "doorStatusOverall";
|
||||
public static final String MB_KEY_WINDOW_STATUS_OVERALL = "windowStatusOverall";
|
||||
public static final String MB_KEY_DOOR_LOCK_STATUS_OVERALL = "doorLockStatusOverall";
|
||||
public static final String MB_KEY_TIRE_MARKER_FRONT_RIGHT = "tireMarkerFrontRight";
|
||||
public static final String MB_KEY_TIRE_MARKER_FRONT_LEFT = "tireMarkerFrontLeft";
|
||||
public static final String MB_KEY_TIRE_MARKER_REAR_RIGHT = "tireMarkerRearRight";
|
||||
public static final String MB_KEY_TIRE_MARKER_REAR_LEFT = "tireMarkerRearLeft";
|
||||
public static final String MB_KEY_PARKBRAKESTATUS = "parkbrakestatus";
|
||||
public static final String MB_KEY_PRECOND_NOW = "precondNow";
|
||||
public static final String MB_KEY_PRECOND_SEAT_FRONT_RIGHT = "precondSeatFrontRight";
|
||||
public static final String MB_KEY_PRECOND_SEAT_FRONT_LEFT = "precondSeatFrontLeft";
|
||||
public static final String MB_KEY_PRECOND_SEAT_REAR_RIGHT = "precondSeatRearRight";
|
||||
public static final String MB_KEY_PRECOND_SEAT_REAR_LEFT = "precondSeatRearLeft";
|
||||
public static final String MB_KEY_WARNINGBRAKEFLUID = "warningbrakefluid";
|
||||
public static final String MB_KEY_WARNINGBRAKELININGWEAR = "warningbrakeliningwear";
|
||||
public static final String MB_KEY_WARNINGWASHWATER = "warningwashwater";
|
||||
public static final String MB_KEY_WARNINGCOOLANTLEVELLOW = "warningcoolantlevellow";
|
||||
public static final String MB_KEY_WARNINGENGINELIGHT = "warningenginelight";
|
||||
public static final String MB_KEY_CHARGINGACTIVE = "chargingactive";
|
||||
public static final String MB_KEY_DOORLOCKSTATUSFRONTRIGHT = "doorlockstatusfrontright";
|
||||
public static final String MB_KEY_DOORLOCKSTATUSFRONTLEFT = "doorlockstatusfrontleft";
|
||||
public static final String MB_KEY_DOORLOCKSTATUSREARRIGHT = "doorlockstatusrearright";
|
||||
public static final String MB_KEY_DOORLOCKSTATUSREARLEFT = "doorlockstatusrearleft";
|
||||
public static final String MB_KEY_DOORLOCKSTATUSDECKLID = "doorlockstatusdecklid";
|
||||
public static final String MB_KEY_DOORLOCKSTATUSGAS = "doorlockstatusgas";
|
||||
public static final String MB_KEY_TIREPRESSURE_FRONT_LEFT = "tirepressureFrontLeft";
|
||||
public static final String MB_KEY_TIREPRESSURE_FRONT_RIGHT = "tirepressureFrontRight";
|
||||
public static final String MB_KEY_TIREPRESSURE_REAR_LEFT = "tirepressureRearLeft";
|
||||
public static final String MB_KEY_POSITION_HEADING = "positionHeading";
|
||||
public static final String MB_KEY_TIREPRESSURE_REAR_RIGHT = "tirepressureRearRight";
|
||||
public static final String MB_KEY_ENGINE_HOOD_STATUS = "engineHoodStatus";
|
||||
public static final String MB_KEY_DECKLIDSTATUS = "decklidstatus";
|
||||
public static final String MB_KEY_DOORSTATUSREARLEFT = "doorstatusrearleft";
|
||||
public static final String MB_KEY_DOORSTATUSREARRIGHT = "doorstatusrearright";
|
||||
public static final String MB_KEY_DOORSTATUSFRONTLEFT = "doorstatusfrontleft";
|
||||
public static final String MB_KEY_DOORSTATUSFRONTRIGHT = "doorstatusfrontright";
|
||||
public static final String MB_KEY_TANKLEVELPERCENT = "tanklevelpercent";
|
||||
public static final String MB_KEY_SOC = "soc";
|
||||
public static final String MB_KEY_TIRE_PRESS_MEAS_TIMESTAMP = "tirePressMeasTimestamp";
|
||||
public static final String MB_KEY_ENDOFCHARGETIME = "endofchargetime";
|
||||
public static final String MB_KEY_LIQUIDCONSUMPTIONRESET = "liquidconsumptionreset";
|
||||
public static final String MB_KEY_LIQUIDCONSUMPTIONSTART = "liquidconsumptionstart";
|
||||
public static final String MB_KEY_ELECTRICCONSUMPTIONRESET = "electricconsumptionreset";
|
||||
public static final String MB_KEY_ELECTRICCONSUMPTIONSTART = "electricconsumptionstart";
|
||||
public static final String MB_KEY_AVERAGE_SPEED_RESET = "averageSpeedReset";
|
||||
public static final String MB_KEY_AVERAGE_SPEED_START = "averageSpeedStart";
|
||||
public static final String MB_KEY_CHARGING_POWER = "chargingPower";
|
||||
public static final String MB_KEY_DRIVEN_TIME_RESET = "drivenTimeReset";
|
||||
public static final String MB_KEY_DRIVEN_TIME_START = "drivenTimeStart";
|
||||
public static final String MB_KEY_DISTANCE_RESET = "distanceReset";
|
||||
public static final String MB_KEY_DISTANCE_START = "distanceStart";
|
||||
public static final String MB_KEY_RANGELIQUID = "rangeliquid";
|
||||
public static final String MB_KEY_OVERALL_RANGE = "overallRange";
|
||||
public static final String MB_KEY_RANGEELECTRIC = "rangeelectric";
|
||||
public static final String MB_KEY_ODO = "odo";
|
||||
public static final String MB_KEY_POSITION_LONG = "positionLong";
|
||||
public static final String MB_KEY_POSITION_LAT = "positionLat";
|
||||
public static final String MB_KEY_TEMPERATURE_POINTS = "temperaturePoints";
|
||||
public static final String MB_KEY_SELECTED_CHARGE_PROGRAM = "selectedChargeProgram";
|
||||
public static final String MB_KEY_CHARGE_PROGRAMS = "chargePrograms";
|
||||
public static final String MB_KEY_COMMAND_CAPABILITIES = "command-capabilities";
|
||||
public static final String MB_KEY_FEATURE_CAPABILITIES = "feature-capabilities";
|
||||
public static final String MB_KEY_COMMAND_ZEV_PRECONDITION_CONFIGURE_SEATS = "commandZevPreconditionConfigureSeats";
|
||||
public static final String MB_KEY_COMMAND_SUNROOF_OPEN = "commandSunroofOpen";
|
||||
public static final String MB_KEY_COMMAND_CHARGE_PROGRAM_CONFIGURE = "commandChargeProgramConfigure";
|
||||
public static final String MB_KEY_COMMAND_SIGPOS_START = "commandSigposStart";
|
||||
public static final String MB_KEY_FEATURE_AUX_HEAT = "featureAuxHeat";
|
||||
public static final String MB_KEY_COMMAND_ZEV_PRECONDITIONING_START = "commandZevPreconditioningStart";
|
||||
public static final String MB_KEY_COMMAND_ZEV_PRECONDITION_CONFIGURE = "commandZevPreconditionConfigure";
|
||||
public static final String MB_KEY_COMMAND_DOORS_LOCK = "commandDoorsLock";
|
||||
public static final String MB_KEY_COMMAND_WINDOWS_OPEN = "commandWindowsOpen";
|
||||
public static final String MB_KEY_COMMAND_ENGINE_START = "commandEngineStart";
|
||||
|
||||
public static final String GROUP_VEHICLE = "vehicle";
|
||||
public static final String GROUP_DOORS = "doors";
|
||||
public static final String GROUP_WINDOWS = "windows";
|
||||
public static final String GROUP_LOCK = "lock";
|
||||
public static final String GROUP_LIGHTS = "lights";
|
||||
public static final String GROUP_LOCATION = "location";
|
||||
public static final String GROUP_IMAGE = "image";
|
||||
public static final String GROUP_WINDOWS = "windows";
|
||||
public static final String GROUP_HVAC = "hvac";
|
||||
public static final String GROUP_SERVICE = "service";
|
||||
public static final String GROUP_RANGE = "range";
|
||||
public static final String GROUP_CHARGE = "charge";
|
||||
public static final String GROUP_TRIP = "trip";
|
||||
public static final String GROUP_POSITION = "position";
|
||||
public static final String GROUP_TIRES = "tires";
|
||||
public static final String GROUP_COMMAND = "command";
|
||||
|
||||
public static final String MB_AUTH_URL = "https://ssoalpha.dvb.corpinter.net/v1/auth";
|
||||
public static final String MB_TOKEN_URL = "https://ssoalpha.dvb.corpinter.net/v1/token";
|
||||
public static final String CALLBACK_ENDPOINT = "/mb-callback";
|
||||
public static final String OAUTH_CLIENT_NAME = "#byocar";
|
||||
|
||||
// https://developer.mercedes-benz.com/products/electric_vehicle_status/docs
|
||||
public static final String SCOPE_EV = "mb:vehicle:mbdata:evstatus";
|
||||
// https://developer.mercedes-benz.com/products/fuel_status/docs
|
||||
public static final String SCOPE_FUEL = "mb:vehicle:mbdata:fuelstatus";
|
||||
// https://developer.mercedes-benz.com/products/pay_as_you_drive_insurance/docs
|
||||
public static final String SCOPE_ODO = "mb:vehicle:mbdata:payasyoudrive";
|
||||
// https://developer.mercedes-benz.com/products/vehicle_lock_status/docs
|
||||
public static final String SCOPE_LOCK = "mb:vehicle:mbdata:vehiclelock";
|
||||
// https://developer.mercedes-benz.com/products/vehicle_status/docs
|
||||
public static final String SCOPE_STATUS = "mb:vehicle:mbdata:vehiclestatus";
|
||||
public static final String SCOPE_OFFLINE = "offline_access";
|
||||
public static final String SCOPE_OPENID = "openid";
|
||||
|
||||
public static final String BASE_URL = "https://api.mercedes-benz.com/vehicledata/v2";
|
||||
public static final String ODO_URL = BASE_URL + "/vehicles/%s/containers/payasyoudrive";
|
||||
public static final String STATUS_URL = BASE_URL + "/vehicles/%s/containers/vehiclestatus";
|
||||
public static final String LOCK_URL = BASE_URL + "/vehicles/%s/containers/vehiclelockstatus";
|
||||
public static final String FUEL_URL = BASE_URL + "/vehicles/%s/containers/fuelstatus";
|
||||
public static final String EV_URL = BASE_URL + "/vehicles/%s/containers/electricvehicle";
|
||||
public static final String OH_CHANNEL_LAST_UPDATE = "last-update";
|
||||
public static final String OH_CHANNEL_SENSOR_AVAILABLE = "sensor-available";
|
||||
public static final String OH_CHANNEL_MARKER_FRONT_LEFT = "marker-front-left";
|
||||
public static final String OH_CHANNEL_MARKER_REAR_LEFT = "marker-rear-left";
|
||||
public static final String OH_CHANNEL_MARKER_FRONT_RIGHT = "marker-front-right";
|
||||
public static final String OH_CHANNEL_MARKER_REAR_RIGHT = "marker-rear-right";
|
||||
public static final String OH_CHANNEL_PRESSURE_FRONT_LEFT = "pressure-front-left";
|
||||
public static final String OH_CHANNEL_PRESSURE_REAR_LEFT = "pressure-rear-left";
|
||||
public static final String OH_CHANNEL_PRESSURE_FRONT_RIGHT = "pressure-front-right";
|
||||
public static final String OH_CHANNEL_PRESSURE_REAR_RIGHT = "pressure-rear-right";
|
||||
public static final String OH_CHANNEL_CONS_CONV_RESET = "cons-conv-reset";
|
||||
public static final String OH_CHANNEL_CONS_EV_RESET = "cons-ev-reset";
|
||||
public static final String OH_CHANNEL_AVG_SPEED_RESET = "avg-speed-reset";
|
||||
public static final String OH_CHANNEL_TIME_RESET = "time-reset";
|
||||
public static final String OH_CHANNEL_DISTANCE_RESET = "distance-reset";
|
||||
public static final String OH_CHANNEL_CONS_CONV = "cons-conv";
|
||||
public static final String OH_CHANNEL_CONS_EV = "cons-ev";
|
||||
public static final String OH_CHANNEL_AVG_SPEED = "avg-speed";
|
||||
public static final String OH_CHANNEL_TIME = "time";
|
||||
public static final String OH_CHANNEL_DISTANCE = "distance";
|
||||
public static final String OH_CHANNEL_HEADING = "heading";
|
||||
public static final String OH_CHANNEL_END_TIME = "end-time";
|
||||
public static final String OH_CHANNEL_POWER = "power";
|
||||
public static final String OH_CHANNEL_COUPLER_LOCK = "coupler-lock";
|
||||
public static final String OH_CHANNEL_COUPLER_DC = "coupler-dc";
|
||||
public static final String OH_CHANNEL_COUPLER_AC = "coupler-ac";
|
||||
public static final String OH_CHANNEL_CHARGE_FLAP = "charge-flap";
|
||||
public static final String OH_CHANNEL_FUEL_LEVEL = "fuel-level";
|
||||
public static final String OH_CHANNEL_RANGE_HYBRID = "range-hybrid";
|
||||
public static final String OH_CHANNEL_RANGE_FUEL = "range-fuel";
|
||||
public static final String OH_CHANNEL_RANGE_ELECTRIC = "range-electric";
|
||||
public static final String OH_CHANNEL_RADIUS_HYBRID = "radius-hybrid";
|
||||
public static final String OH_CHANNEL_RADIUS_FUEL = "radius-fuel";
|
||||
public static final String OH_CHANNEL_RADIUS_ELECTRIC = "radius-electric";
|
||||
public static final String OH_CHANNEL_SERVICE_DAYS = "service-days";
|
||||
public static final String OH_CHANNEL_TIRES_RDK = "tires-rdk";
|
||||
public static final String OH_CHANNEL_ENGINE = "engine";
|
||||
public static final String OH_CHANNEL_COOLANT_FLUID = "coolant-fluid";
|
||||
public static final String OH_CHANNEL_BRAKE_LINING_WEAR = "brake-lining-wear";
|
||||
public static final String OH_CHANNEL_WASH_WATER = "wash-water";
|
||||
public static final String OH_CHANNEL_BRAKE_FLUID = "brake-fluid";
|
||||
public static final String OH_CHANNEL_STARTER_BATTERY = "starter-battery";
|
||||
public static final String OH_CHANNEL_ACTIVE = "active";
|
||||
public static final String OH_CHANNEL_FLIP_WINDOW = "flip-window";
|
||||
public static final String OH_CHANNEL_REAR_BLIND = "rear-blind";
|
||||
public static final String OH_CHANNEL_REAR_LEFT_BLIND = "rear-left-blind";
|
||||
public static final String OH_CHANNEL_REAR_RIGHT_BLIND = "rear-right-blind";
|
||||
public static final String OH_CHANNEL_GAS_FLAP = "gas-flap";
|
||||
public static final String OH_CHANNEL_ROOFTOP = "rooftop";
|
||||
public static final String OH_CHANNEL_SUNROOF_REAR_BLIND = "sunroof-rear-blind";
|
||||
public static final String OH_CHANNEL_SUNROOF_FRONT_BLIND = "sunroof-front-blind";
|
||||
public static final String OH_CHANNEL_SUNROOF = "sunroof";
|
||||
public static final String OH_CHANNEL_ENGINE_HOOD = "engine-hood";
|
||||
public static final String OH_CHANNEL_DECK_LID = "deck-lid";
|
||||
public static final String OH_CHANNEL_REAR_LEFT = "rear-left";
|
||||
public static final String OH_CHANNEL_REAR_RIGHT = "rear-right";
|
||||
public static final String OH_CHANNEL_FRONT_LEFT = "front-left";
|
||||
public static final String OH_CHANNEL_FRONT_RIGHT = "front-right";
|
||||
public static final String OH_CHANNEL_PARK_BRAKE = "park-brake";
|
||||
public static final String OH_CHANNEL_IGNITION = "ignition";
|
||||
public static final String OH_CHANNEL_DOOR_STATUS = "door-status";
|
||||
public static final String OH_CHANNEL_WINDOWS = "windows";
|
||||
public static final String OH_CHANNEL_LOCK = "lock";
|
||||
public static final String OH_CHANNEL_MILEAGE = "mileage";
|
||||
public static final String OH_CHANNEL_TEMPERATURE = "temperature";
|
||||
public static final String OH_CHANNEL_AUX_HEAT = "aux-heat";
|
||||
public static final String OH_CHANNEL_ZONE = "zone";
|
||||
public static final String OH_CHANNEL_SIGNAL = "signal";
|
||||
public static final String OH_CHANNEL_AUTO_UNLOCK = "auto-unlock";
|
||||
public static final String OH_CHANNEL_MAX_SOC = "max-soc";
|
||||
public static final String OH_CHANNEL_PROGRAM = "program";
|
||||
public static final String OH_CHANNEL_CMD_LAST_UPDATE = "cmd-last-update";
|
||||
public static final String OH_CHANNEL_CMD_STATE = "cmd-state";
|
||||
public static final String OH_CHANNEL_CMD_NAME = "cmd-name";
|
||||
public static final String OH_CHANNEL_PROTO_UPDATE = "proto-update";
|
||||
public static final String OH_CHANNEL_SOC = "soc";
|
||||
public static final String OH_CHANNEL_UNCHARGED = "uncharged";
|
||||
public static final String OH_CHANNEL_CHARGED = "charged";
|
||||
public static final String OH_CHANNEL_TANK_OPEN = "tank-open";
|
||||
public static final String OH_CHANNEL_TANK_REMAIN = "tank-remain";
|
||||
public static final String OH_CHANNEL_HOME_DISTANCE = "home-distance";
|
||||
public static final String OH_CHANNEL_GPS = "gps";
|
||||
public static final String OH_CHANNEL_CONS_CONV_UNIT = "cons-conv-unit";
|
||||
public static final String OH_CHANNEL_CONS_EV_UNIT = "cons-ev-unit";
|
||||
|
||||
public static final String CALLBACK_ENDPOINT = "/mb-auth";
|
||||
// https://developer.mercedes-benz.com/content-page/api_migration_guide
|
||||
public static final String IMAGE_BASE_URL = "https://api.mercedes-benz.com/vehicle_images/v2";
|
||||
public static final String IMAGE_EXTERIOR_RESOURCE_URL = IMAGE_BASE_URL + "/vehicles/%s";
|
||||
|
||||
public static final String STATUS_TEXT_PREFIX = "@text/mercedesme.";
|
||||
public static final String STATUS_AUTH_NEEDED = ".status.authorization-needed";
|
||||
public static final String STATUS_EMAIL_MISSING = ".status.email-missing";
|
||||
public static final String STATUS_REGION_MISSING = ".status.region-missing";
|
||||
public static final String STATUS_REFRESH_INVALID = ".status.refresh-invalid";
|
||||
public static final String STATUS_IP_MISSING = ".status.ip-missing";
|
||||
public static final String STATUS_PORT_MISSING = ".status.port-missing";
|
||||
public static final String STATUS_CLIENT_ID_MISSING = ".status.client-id-missing";
|
||||
public static final String STATUS_CLIENT_SECRET_MISSING = ".status.client-secret-missing";
|
||||
public static final String STATUS_SERVER_RESTART = ".status.server-restart";
|
||||
public static final String STATUS_BRIDGE_MISSING = ".status.bridge-missing";
|
||||
public static final String STATUS_BRIDGE_ATHORIZATION = ".status.bridge-authoriziation";
|
||||
|
||||
public static final String SPACE = " ";
|
||||
public static final String EMPTY = "";
|
||||
public static final String COLON = ":";
|
||||
public static final String NOT_SET = "not set";
|
||||
public static final String UNRECOGNIZED = "UNRECOGNIZED";
|
||||
|
||||
public static final String CODE = "code";
|
||||
public static final String GUID = "guid";
|
||||
public static final String PIN = "pin";
|
||||
public static final String MIME_PREFIX = "image/";
|
||||
|
||||
public static final Unit<Length> KILOMETRE_UNIT = MetricPrefix.KILO(SIUnits.METRE);
|
||||
public static final Unit<Power> KILOWATT_UNIT = MetricPrefix.KILO(Units.WATT);
|
||||
public static final Unit<Energy> KILOWATT_HOUR_UNIT = MetricPrefix.KILO(Units.WATT_HOUR);
|
||||
public static final Unit<Pressure> KPA_UNIT = MetricPrefix.KILO(SIUnits.PASCAL);
|
||||
|
||||
public static final String LOGIN_APP_ID = "01398c1c-dc45-4b42-882b-9f5ba9f175f1";
|
||||
public static final String LOGIN_APP_ID_EU = "01398c1c-dc45-4b42-882b-9f5ba9f175f1";
|
||||
public static final String LOGIN_APP_ID_CN = "3f36efb1-f84b-4402-b5a2-68a118fec33e";
|
||||
public static final String LOGIN_BASE_URI = "https://id.mercedes-benz.com";
|
||||
public static final String LOGIN_BASE_URI_CN = "https://ciam-1.mercedes-benz.com.cn";
|
||||
public static final String LOGIN_BASE_URI_NA = "https://id.mercedes-benz.com";
|
||||
public static final String LOGIN_BASE_URI_PA = "https://id.mercedes-benz.com";
|
||||
public static final String PSAG_BASE_URI = "https://psag.query.api.dvb.corpinter.net";
|
||||
public static final String PSAG_BASE_URI_CN = "https://psag.query.api.dvb.corpinter.net.cn";
|
||||
public static final String RCP_BASE_URI = "https://rcp-rs.query.api.dvb.corpinter.net";
|
||||
public static final String RCP_BASE_URI_CN = "https://rcp-rs.query.api.dvb.corpinter.net.cn";
|
||||
public static final String REST_API_BASE = "https://bff.emea-prod.mobilesdk.mercedes-benz.com";
|
||||
public static final String REST_API_BASE_CN = "https://bff.cn-prod.mobilesdk.mercedes-benz.com";
|
||||
public static final String REST_API_BASE_NA = "https://bff.amap-prod.mobilesdk.mercedes-benz.com";
|
||||
public static final String REST_API_BASE_PA = "https://bff.amap-prod.mobilesdk.mercedes-benz.com";
|
||||
public static final String WEBSOCKET_API_BASE = "wss://websocket.emea-prod.mobilesdk.mercedes-benz.com/ws";
|
||||
public static final String WEBSOCKET_API_BASE_NA = "wss://websocket.amap-prod.mobilesdk.mercedes-benz.com/ws";
|
||||
public static final String WEBSOCKET_API_BASE_PA = "wss://websocket.amap-prod.mobilesdk.mercedes-benz.com/ws";
|
||||
public static final String WEBSOCKET_API_BASE_CN = "wss://websocket.cn-prod.mobilesdk.mercedes-benz.com/ws";
|
||||
public static final String WEBSOCKET_USER_AGENT = "MyCar/1.30.1 (com.daimler.ris.mercedesme.ece.ios; build:1819; iOS 16.5.0) Alamofire/5.4.0";
|
||||
public static final String WEBSOCKET_USER_AGENT_CN = "MyStarCN/1.27.0 (com.daimler.ris.mercedesme.cn.ios; build:1758; iOS 16.3.1) Alamofire/5.4.0";
|
||||
public static final String WEBSOCKET_USER_AGENT_PA = "mycar-store-ap v1.27.0, android 8.0.0, SDK 2.84.3";
|
||||
|
||||
public static final String RIS_APPLICATION_VERSION_NA = "3.40.0";
|
||||
public static final String RIS_APPLICATION_VERSION_CN = "1.39.0";
|
||||
public static final String RIS_APPLICATION_VERSION_PA = "1.40.0";
|
||||
public static final String RIS_APPLICATION_VERSION = "1.42.0 (2168)";
|
||||
public static final String RIS_SDK_VERSION = "2.114.0";
|
||||
public static final String RIS_SDK_VERSION_CN = "2.109.2";
|
||||
public static final String RIS_OS_VERSION = "17.4.1";
|
||||
public static final String RIS_OS_NAME = "ios";
|
||||
public static final String X_APPLICATIONNAME = "mycar-store-ece";
|
||||
public static final String X_APPLICATIONNAME_ECE = "mycar-store-ece";
|
||||
public static final String X_APPLICATIONNAME_CN = "mycar-store-cn";
|
||||
public static final String X_APPLICATIONNAME_US = "mycar-store-us";
|
||||
public static final String X_APPLICATIONNAME_AP = "mycar-store-ap";
|
||||
|
||||
public static final String REGION_EUROPE = "EU";
|
||||
public static final String REGION_NORAM = "NA";
|
||||
public static final String REGION_APAC = "AP";
|
||||
public static final String REGION_CHINA = "CN";
|
||||
|
||||
public static final String SCOPE = "openid email phone profile offline_access ciam-uid";
|
||||
|
||||
public static final String MAX_SOC_KEY = "maxsoc";
|
||||
public static final String AUTO_UNLOCK_KEY = "autolock";
|
||||
|
||||
public static final String JUNIT_SERVER_ADDR = "http://999.999.999.999:99999/mb-auth";
|
||||
public static final String JUNIT_TOKEN = "junitTestToken";
|
||||
public static final String JUNIT_REFRESH_TOKEN = "junitRefreshToken";
|
||||
}
|
||||
|
@ -19,12 +19,19 @@ import java.util.Set;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.eclipse.jetty.client.WWWAuthenticationProtocolHandler;
|
||||
import org.openhab.binding.mercedesme.internal.discovery.MercedesMeDiscoveryService;
|
||||
import org.openhab.binding.mercedesme.internal.handler.AccountHandler;
|
||||
import org.openhab.binding.mercedesme.internal.handler.VehicleHandler;
|
||||
import org.openhab.core.auth.client.oauth2.OAuthFactory;
|
||||
import org.openhab.binding.mercedesme.internal.utils.Mapper;
|
||||
import org.openhab.binding.mercedesme.internal.utils.Utils;
|
||||
import org.openhab.core.config.discovery.DiscoveryService;
|
||||
import org.openhab.core.i18n.LocaleProvider;
|
||||
import org.openhab.core.i18n.LocationProvider;
|
||||
import org.openhab.core.i18n.TimeZoneProvider;
|
||||
import org.openhab.core.i18n.UnitProvider;
|
||||
import org.openhab.core.io.net.http.HttpClientFactory;
|
||||
import org.openhab.core.items.MetadataRegistry;
|
||||
import org.openhab.core.net.NetworkAddressService;
|
||||
import org.openhab.core.storage.StorageService;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
import org.openhab.core.thing.Thing;
|
||||
@ -32,16 +39,16 @@ import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.thing.binding.BaseThingHandlerFactory;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandlerFactory;
|
||||
import org.openhab.core.thing.link.ItemChannelLinkRegistry;
|
||||
import org.osgi.framework.Bundle;
|
||||
import org.osgi.framework.ServiceRegistration;
|
||||
import org.osgi.service.component.ComponentContext;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link MercedesMeHandlerFactory} is responsible for creating things and thing
|
||||
* handlers.
|
||||
* The {@link MercedesMeHandlerFactory} is responsible for creating thing handlers.
|
||||
*
|
||||
* @author Bernd Weymann - Initial contribution
|
||||
*/
|
||||
@ -51,31 +58,38 @@ public class MercedesMeHandlerFactory extends BaseThingHandlerFactory {
|
||||
private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Set.of(THING_TYPE_BEV, THING_TYPE_COMB,
|
||||
THING_TYPE_HYBRID, THING_TYPE_ACCOUNT);
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(MercedesMeHandlerFactory.class);
|
||||
private final OAuthFactory oAuthFactory;
|
||||
private final HttpClient httpClient;
|
||||
private final LocaleProvider localeProvider;
|
||||
private final LocationProvider locationProvider;
|
||||
private final StorageService storageService;
|
||||
private final MercedesMeDiscoveryService discoveryService;
|
||||
private final MercedesMeCommandOptionProvider mmcop;
|
||||
private final MercedesMeStateOptionProvider mmsop;
|
||||
private final StorageService storageService;
|
||||
private final TimeZoneProvider timeZoneProvider;
|
||||
private final NetworkAddressService networkService;
|
||||
private @Nullable ServiceRegistration<?> discoveryServiceReg;
|
||||
private @Nullable MercedesMeMetadataAdjuster mdAdjuster;
|
||||
|
||||
public static String ohVersion = "unknown";
|
||||
|
||||
@Activate
|
||||
public MercedesMeHandlerFactory(@Reference OAuthFactory oAuthFactory, @Reference HttpClientFactory hcf,
|
||||
@Reference StorageService storageService, final @Reference MercedesMeCommandOptionProvider cop,
|
||||
final @Reference MercedesMeStateOptionProvider sop, final @Reference TimeZoneProvider tzp) {
|
||||
this.oAuthFactory = oAuthFactory;
|
||||
public MercedesMeHandlerFactory(@Reference HttpClientFactory hcf, @Reference StorageService storageService,
|
||||
final @Reference LocaleProvider lp, final @Reference LocationProvider locationP,
|
||||
final @Reference TimeZoneProvider tzp, final @Reference MercedesMeCommandOptionProvider cop,
|
||||
final @Reference MercedesMeStateOptionProvider sop, final @Reference UnitProvider up,
|
||||
final @Reference MetadataRegistry mdr, final @Reference ItemChannelLinkRegistry iclr,
|
||||
final @Reference NetworkAddressService nas) {
|
||||
this.storageService = storageService;
|
||||
networkService = nas;
|
||||
localeProvider = lp;
|
||||
locationProvider = locationP;
|
||||
mmcop = cop;
|
||||
mmsop = sop;
|
||||
timeZoneProvider = tzp;
|
||||
httpClient = hcf.createHttpClient(Constants.BINDING_ID);
|
||||
// https://github.com/jetty-project/jetty-reactive-httpclient/issues/33
|
||||
httpClient.getProtocolHandlers().remove(WWWAuthenticationProtocolHandler.NAME);
|
||||
try {
|
||||
httpClient.start();
|
||||
} catch (Exception e) {
|
||||
logger.warn("HTTP client not started: {} - no web access possible!", e.getLocalizedMessage());
|
||||
}
|
||||
|
||||
Utils.initialize(tzp, lp);
|
||||
Mapper.initialize(up);
|
||||
mdAdjuster = new MercedesMeMetadataAdjuster(mdr, iclr, up);
|
||||
httpClient = hcf.getCommonHttpClient();
|
||||
discoveryService = new MercedesMeDiscoveryService();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -85,21 +99,41 @@ public class MercedesMeHandlerFactory extends BaseThingHandlerFactory {
|
||||
|
||||
@Override
|
||||
protected @Nullable ThingHandler createHandler(Thing thing) {
|
||||
Bundle[] bundleList = this.getBundleContext().getBundles();
|
||||
for (int i = 0; i < bundleList.length; i++) {
|
||||
if ("org.openhab.binding.mercedesme".equals(bundleList[i].getSymbolicName())) {
|
||||
ohVersion = bundleList[i].getVersion().toString();
|
||||
}
|
||||
}
|
||||
|
||||
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
||||
if (THING_TYPE_ACCOUNT.equals(thingTypeUID)) {
|
||||
return new AccountHandler((Bridge) thing, httpClient, oAuthFactory);
|
||||
if (discoveryServiceReg == null) {
|
||||
discoveryServiceReg = bundleContext.registerService(DiscoveryService.class.getName(), discoveryService,
|
||||
null);
|
||||
}
|
||||
return new AccountHandler((Bridge) thing, discoveryService, httpClient, localeProvider, storageService,
|
||||
networkService);
|
||||
} else if (THING_TYPE_BEV.equals(thingTypeUID) || THING_TYPE_COMB.equals(thingTypeUID)
|
||||
|| THING_TYPE_HYBRID.equals(thingTypeUID)) {
|
||||
return new VehicleHandler(thing, locationProvider, mmcop, mmsop);
|
||||
}
|
||||
return new VehicleHandler(thing, httpClient, thingTypeUID.getId(), storageService, mmcop, mmsop,
|
||||
timeZoneProvider);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void deactivate(ComponentContext componentContext) {
|
||||
super.deactivate(componentContext);
|
||||
try {
|
||||
httpClient.stop();
|
||||
} catch (Exception e) {
|
||||
logger.debug("HTTP client not stopped: {}", e.getLocalizedMessage());
|
||||
if (discoveryServiceReg != null) {
|
||||
discoveryServiceReg.unregister();
|
||||
discoveryServiceReg = null;
|
||||
}
|
||||
if (mdAdjuster != null) {
|
||||
mdAdjuster = null;
|
||||
}
|
||||
}
|
||||
|
||||
public static String getVersion() {
|
||||
return ohVersion;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,110 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.mercedesme.internal;
|
||||
|
||||
import javax.measure.Unit;
|
||||
import javax.measure.quantity.Length;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.common.registry.RegistryChangeListener;
|
||||
import org.openhab.core.i18n.UnitProvider;
|
||||
import org.openhab.core.items.Metadata;
|
||||
import org.openhab.core.items.MetadataKey;
|
||||
import org.openhab.core.items.MetadataRegistry;
|
||||
import org.openhab.core.library.unit.ImperialUnits;
|
||||
import org.openhab.core.library.unit.SIUnits;
|
||||
import org.openhab.core.library.unit.Units;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.link.ItemChannelLink;
|
||||
import org.openhab.core.thing.link.ItemChannelLinkRegistry;
|
||||
|
||||
/**
|
||||
* {@link MercedesMeMetadataAdjuster} changes Metadata for channels not providing the system default unit
|
||||
*
|
||||
* @author Bernd Weymann - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class MercedesMeMetadataAdjuster implements RegistryChangeListener<ItemChannelLink> {
|
||||
private final MetadataRegistry metadataRegistry;
|
||||
private final ItemChannelLinkRegistry channelLinkRegistry;
|
||||
private final UnitProvider unitProvider;
|
||||
|
||||
public MercedesMeMetadataAdjuster(MetadataRegistry mdr, ItemChannelLinkRegistry iclr, UnitProvider up) {
|
||||
metadataRegistry = mdr;
|
||||
channelLinkRegistry = iclr;
|
||||
unitProvider = up;
|
||||
channelLinkRegistry.addRegistryChangeListener(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjust Units to binding defaults
|
||||
*/
|
||||
@Override
|
||||
public void added(ItemChannelLink element) {
|
||||
ChannelUID cuid = element.getLinkedUID();
|
||||
String itemName = element.getItemName();
|
||||
if (Constants.BINDING_ID.equals(cuid.getBindingId())) {
|
||||
MetadataKey key = new MetadataKey("unit", itemName);
|
||||
switch (cuid.getId()) {
|
||||
case Constants.GROUP_RANGE + ChannelUID.CHANNEL_GROUP_SEPARATOR + "mileage":
|
||||
case Constants.GROUP_RANGE + ChannelUID.CHANNEL_GROUP_SEPARATOR + "range-electric":
|
||||
case Constants.GROUP_RANGE + ChannelUID.CHANNEL_GROUP_SEPARATOR + "radius-electric":
|
||||
case Constants.GROUP_RANGE + ChannelUID.CHANNEL_GROUP_SEPARATOR + "range-fuel":
|
||||
case Constants.GROUP_RANGE + ChannelUID.CHANNEL_GROUP_SEPARATOR + "radius-fuel":
|
||||
case Constants.GROUP_RANGE + ChannelUID.CHANNEL_GROUP_SEPARATOR + "range-hybrid":
|
||||
case Constants.GROUP_RANGE + ChannelUID.CHANNEL_GROUP_SEPARATOR + "radius-hybrid":
|
||||
case Constants.GROUP_RANGE + ChannelUID.CHANNEL_GROUP_SEPARATOR + "home-distance":
|
||||
case Constants.GROUP_TRIP + ChannelUID.CHANNEL_GROUP_SEPARATOR + "distance":
|
||||
case Constants.GROUP_TRIP + ChannelUID.CHANNEL_GROUP_SEPARATOR + "distance-reset":
|
||||
if (metadataRegistry.get(key) == null) {
|
||||
Unit<Length> lengthUnit = unitProvider.getUnit(Length.class);
|
||||
if (ImperialUnits.FOOT.equals(lengthUnit)) {
|
||||
metadataRegistry.add(new Metadata(key, ImperialUnits.MILE.getSymbol(), null));
|
||||
} else if (SIUnits.METRE.equals(lengthUnit)) {
|
||||
metadataRegistry.add(new Metadata(key, Constants.KILOMETRE_UNIT.toString(), null));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Constants.GROUP_RANGE + ChannelUID.CHANNEL_GROUP_SEPARATOR + "soc":
|
||||
case Constants.GROUP_CHARGE + ChannelUID.CHANNEL_GROUP_SEPARATOR + "max-soc":
|
||||
case Constants.GROUP_RANGE + ChannelUID.CHANNEL_GROUP_SEPARATOR + "fuel-level":
|
||||
if (metadataRegistry.get(key) == null) {
|
||||
metadataRegistry.add(new Metadata(key, Units.PERCENT.getSymbol(), null));
|
||||
}
|
||||
break;
|
||||
case Constants.GROUP_TIRES + ChannelUID.CHANNEL_GROUP_SEPARATOR + "pressure-front-left":
|
||||
case Constants.GROUP_TIRES + ChannelUID.CHANNEL_GROUP_SEPARATOR + "pressure-front-right":
|
||||
case Constants.GROUP_TIRES + ChannelUID.CHANNEL_GROUP_SEPARATOR + "pressure-rear-left":
|
||||
case Constants.GROUP_TIRES + ChannelUID.CHANNEL_GROUP_SEPARATOR + "pressure-rear-right":
|
||||
if (metadataRegistry.get(key) == null) {
|
||||
Unit<Length> lengthUnit = unitProvider.getUnit(Length.class);
|
||||
if (ImperialUnits.FOOT.equals(lengthUnit)) {
|
||||
metadataRegistry
|
||||
.add(new Metadata(key, ImperialUnits.POUND_FORCE_SQUARE_INCH.getSymbol(), null));
|
||||
} else if (SIUnits.METRE.equals(lengthUnit)) {
|
||||
metadataRegistry.add(new Metadata(key, Units.BAR.getSymbol(), null));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removed(ItemChannelLink element) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updated(ItemChannelLink oldElement, ItemChannelLink element) {
|
||||
}
|
||||
}
|
@ -0,0 +1,94 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.mercedesme.internal.actions;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
import org.openhab.binding.mercedesme.internal.handler.VehicleHandler;
|
||||
import org.openhab.core.automation.annotation.ActionInput;
|
||||
import org.openhab.core.automation.annotation.RuleAction;
|
||||
import org.openhab.core.thing.binding.ThingActions;
|
||||
import org.openhab.core.thing.binding.ThingActionsScope;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
|
||||
/**
|
||||
* {@link VehicleActions} which can be sent to a vehicle
|
||||
*
|
||||
* @author Bernd Weymann - Initial contribution
|
||||
*/
|
||||
@ThingActionsScope(name = "mercedesme")
|
||||
@NonNullByDefault
|
||||
public class VehicleActions implements ThingActions {
|
||||
private Optional<VehicleHandler> thingHandler = Optional.empty();
|
||||
private String[] argumentKey = new String[] { "city", "street", "postcode" };
|
||||
|
||||
@RuleAction(label = "@text/actionPoiLabel", description = "@text/actionPoiDescription")
|
||||
/**
|
||||
* Send Point of Interest (POI) to your vehicle.
|
||||
* This POI is shown in your vehicle messages and can be instantly used to start a navigation route to this point.
|
||||
* A "catchy" title plus latitude / longitude are mandatory.
|
||||
* Parameters args is optional. If you use it respect the following order
|
||||
* 1) City
|
||||
* 2) Street
|
||||
* 3) Postal Code
|
||||
* If you miss any of them provide an empty String
|
||||
*
|
||||
* @param title - the title will be shown in your vehicle message inbox
|
||||
* @param latitude - latitude of POI location
|
||||
* @param longitude - longitude of POI location
|
||||
* @param args - optional but respect order city, street, postal code
|
||||
*/
|
||||
public void sendPoi(
|
||||
@ActionInput(name = "title", label = "@text/poiTitle", description = "@text/poiTitleDescription") String title,
|
||||
@ActionInput(name = "latitude", label = "@text/latitudeLabel", description = "@text/latitudeDescription") double latitude,
|
||||
@ActionInput(name = "longitude", label = "@text/longitudeLabel", description = "@text/longitudeDescription") double longitude,
|
||||
String... args) {
|
||||
if (thingHandler.isPresent()) {
|
||||
JSONObject poi = new JSONObject();
|
||||
poi.put("routeTitle", title);
|
||||
poi.put("routeType", "singlePOI");
|
||||
JSONArray waypoints = new JSONArray();
|
||||
JSONObject waypoint = new JSONObject();
|
||||
waypoint.put("title", title);
|
||||
waypoint.put("latitude", latitude);
|
||||
waypoint.put("longitude", longitude);
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
waypoint.put(argumentKey[i], args[i]);
|
||||
}
|
||||
waypoints.put(waypoint);
|
||||
poi.put("waypoints", waypoints);
|
||||
thingHandler.get().sendPoi(poi);
|
||||
}
|
||||
}
|
||||
|
||||
public static void sendPoi(ThingActions actions, String title, double lat, double lon, String... args) {
|
||||
((VehicleActions) actions).sendPoi(title, lat, lon, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setThingHandler(ThingHandler handler) {
|
||||
thingHandler = Optional.of((VehicleHandler) handler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable ThingHandler getThingHandler() {
|
||||
if (thingHandler.isPresent()) {
|
||||
return thingHandler.get();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -12,56 +12,23 @@
|
||||
*/
|
||||
package org.openhab.binding.mercedesme.internal.config;
|
||||
|
||||
import static org.openhab.binding.mercedesme.internal.Constants.*;
|
||||
import static org.openhab.binding.mercedesme.internal.Constants.NOT_SET;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link AccountConfiguration} class contains fields mapping thing configuration parameters.
|
||||
* {@link AccountConfiguration} for Account Bridge
|
||||
*
|
||||
* @author Bernd Weymann - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class AccountConfiguration {
|
||||
|
||||
public String clientId = NOT_SET;
|
||||
public String clientSecret = NOT_SET;
|
||||
public String imageApiKey = NOT_SET;
|
||||
public String email = NOT_SET;
|
||||
public String region = NOT_SET;
|
||||
public String pin = NOT_SET;
|
||||
public int refreshInterval = 15;
|
||||
|
||||
// Advanced Parameters
|
||||
public String callbackIP = NOT_SET;
|
||||
public int callbackPort = -1;
|
||||
public boolean odoScope = true;
|
||||
public boolean vehicleScope = true;
|
||||
public boolean lockScope = true;
|
||||
public boolean fuelScope = true;
|
||||
public boolean evScope = true;
|
||||
|
||||
// https://developer.mercedes-benz.com/products/electric_vehicle_status/docs#_required_scopes
|
||||
public String getScope() {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append(SCOPE_OPENID).append(SPACE).append(SCOPE_OFFLINE);
|
||||
if (odoScope) {
|
||||
sb.append(SPACE).append(SCOPE_ODO);
|
||||
}
|
||||
if (vehicleScope) {
|
||||
sb.append(SPACE).append(SCOPE_STATUS);
|
||||
}
|
||||
if (lockScope) {
|
||||
sb.append(SPACE).append(SCOPE_LOCK);
|
||||
}
|
||||
if (fuelScope) {
|
||||
sb.append(SPACE).append(SCOPE_FUEL);
|
||||
}
|
||||
if (evScope) {
|
||||
sb.append(SPACE).append(SCOPE_EV);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ID " + clientId + ", Secret " + clientSecret + ", IP " + callbackIP + ", Port " + callbackPort
|
||||
+ ", scope " + getScope();
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.mercedesme.internal.Constants;
|
||||
|
||||
/**
|
||||
* The {@link VehicleConfiguration} class contains fields mapping thing configuration parameters.
|
||||
* {@link VehicleConfiguration} to configure vehicle
|
||||
*
|
||||
* @author Bernd Weymann - Initial contribution
|
||||
*/
|
||||
@ -24,14 +24,6 @@ import org.openhab.binding.mercedesme.internal.Constants;
|
||||
public class VehicleConfiguration {
|
||||
|
||||
public String vin = Constants.NOT_SET;
|
||||
public int refreshInterval = 5;
|
||||
public float batteryCapacity = -1;
|
||||
public float fuelCapacity = -1;
|
||||
|
||||
// Advanced
|
||||
public boolean background = false;
|
||||
public boolean night = false;
|
||||
public boolean cropped = false;
|
||||
public boolean roofOpen = false;
|
||||
public String format = "webp";
|
||||
}
|
||||
|
@ -0,0 +1,89 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.mercedesme.internal.discovery;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.mercedesme.internal.Constants;
|
||||
import org.openhab.binding.mercedesme.internal.handler.AccountHandler;
|
||||
import org.openhab.core.config.discovery.AbstractDiscoveryService;
|
||||
import org.openhab.core.config.discovery.DiscoveryResultBuilder;
|
||||
import org.openhab.core.config.discovery.DiscoveryService;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.thing.ThingUID;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
|
||||
/**
|
||||
* {@link MercedesMeDiscoveryService} will be notified from Bridge {@link AccountHandler} regarding
|
||||
* associated vehicles and provides DiscoveryResults
|
||||
*
|
||||
* @author Bernd Weymann - Initial Contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
@Component(service = DiscoveryService.class, configurationPid = "discovery.mercedesme")
|
||||
public class MercedesMeDiscoveryService extends AbstractDiscoveryService {
|
||||
|
||||
public MercedesMeDiscoveryService() {
|
||||
super(Constants.DISCOVERABLE_DEVICE_TYPE_UIDS, 0, false);
|
||||
}
|
||||
|
||||
public void vehicleDiscovered(AccountHandler ac, String vin, Map<String, Object> properties) {
|
||||
Object vehicleTypeObj = properties.get("vehicle");
|
||||
String vehicleType = ((vehicleTypeObj == null) ? "unknown" : vehicleTypeObj.toString());
|
||||
ThingTypeUID ttuid = null;
|
||||
switch (vehicleType) {
|
||||
case Constants.BEV:
|
||||
ttuid = Constants.THING_TYPE_BEV;
|
||||
break;
|
||||
case Constants.COMBUSTION:
|
||||
ttuid = Constants.THING_TYPE_COMB;
|
||||
break;
|
||||
case Constants.HYBRID:
|
||||
ttuid = Constants.THING_TYPE_HYBRID;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (ttuid != null) {
|
||||
thingDiscovered(DiscoveryResultBuilder.create(new ThingUID(ttuid, ac.getThing().getUID(), vin))
|
||||
.withBridge(ac.getThing().getUID()).withProperties(properties)
|
||||
.withLabel("Mercedes Benz " + ttuid.getId().toUpperCase()).build());
|
||||
}
|
||||
}
|
||||
|
||||
public void vehicleRemove(AccountHandler ac, String vin, String vehicleType) {
|
||||
ThingTypeUID ttuid = null;
|
||||
switch (vehicleType) {
|
||||
case Constants.BEV:
|
||||
ttuid = Constants.THING_TYPE_BEV;
|
||||
break;
|
||||
case Constants.COMBUSTION:
|
||||
ttuid = Constants.THING_TYPE_COMB;
|
||||
break;
|
||||
case Constants.HYBRID:
|
||||
ttuid = Constants.THING_TYPE_HYBRID;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (ttuid != null) {
|
||||
thingRemoved(new ThingUID(ttuid, ac.getThing().getUID(), vin));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startScan() {
|
||||
// not supported
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.mercedesme.internal.dto;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link PINRequest} dto contains JSon body for PIN request
|
||||
*
|
||||
* @author Bernd Weymann - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class PINRequest {
|
||||
public String emailOrPhoneNumber;
|
||||
public String countryCode;
|
||||
public String nonce;
|
||||
|
||||
public PINRequest(String mail, String country) {
|
||||
emailOrPhoneNumber = mail;
|
||||
countryCode = country;
|
||||
nonce = UUID.randomUUID().toString();
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.mercedesme.internal.dto;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.mercedesme.internal.Constants;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* The {@link TokenResponse} dto contains JSon body of token response
|
||||
*
|
||||
* @author Bernd Weymann - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class TokenResponse {
|
||||
@SerializedName("access_token")
|
||||
public String accessToken = Constants.NOT_SET;
|
||||
@SerializedName("refresh_token")
|
||||
public String refreshToken = Constants.NOT_SET;
|
||||
@SerializedName("token_type")
|
||||
public String tokenType = Constants.NOT_SET;
|
||||
@SerializedName("expires_in")
|
||||
public int expiresIn;
|
||||
public String createdOn = Instant.now().toString();
|
||||
}
|
@ -12,19 +12,41 @@
|
||||
*/
|
||||
package org.openhab.binding.mercedesme.internal.handler;
|
||||
|
||||
import java.net.SocketException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.eclipse.jetty.client.api.ContentResponse;
|
||||
import org.eclipse.jetty.client.api.Request;
|
||||
import org.eclipse.jetty.client.util.StringContentProvider;
|
||||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
import org.openhab.binding.mercedesme.internal.Constants;
|
||||
import org.openhab.binding.mercedesme.internal.config.AccountConfiguration;
|
||||
import org.openhab.binding.mercedesme.internal.server.CallbackServer;
|
||||
import org.openhab.binding.mercedesme.internal.server.Utils;
|
||||
import org.openhab.binding.mercedesme.internal.discovery.MercedesMeDiscoveryService;
|
||||
import org.openhab.binding.mercedesme.internal.server.AuthServer;
|
||||
import org.openhab.binding.mercedesme.internal.server.AuthService;
|
||||
import org.openhab.binding.mercedesme.internal.server.MBWebsocket;
|
||||
import org.openhab.binding.mercedesme.internal.utils.Utils;
|
||||
import org.openhab.core.auth.client.oauth2.AccessTokenRefreshListener;
|
||||
import org.openhab.core.auth.client.oauth2.AccessTokenResponse;
|
||||
import org.openhab.core.auth.client.oauth2.OAuthFactory;
|
||||
import org.openhab.core.config.core.Configuration;
|
||||
import org.openhab.core.i18n.LocaleProvider;
|
||||
import org.openhab.core.net.NetworkAddressService;
|
||||
import org.openhab.core.storage.Storage;
|
||||
import org.openhab.core.storage.StorageService;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
@ -34,33 +56,61 @@ import org.openhab.core.types.Command;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.daimler.mbcarkit.proto.Client.ClientMessage;
|
||||
import com.daimler.mbcarkit.proto.VehicleEvents.VEPUpdate;
|
||||
import com.daimler.mbcarkit.proto.Vehicleapi.AppTwinCommandStatusUpdatesByPID;
|
||||
|
||||
/**
|
||||
* The {@link AccountHandler} takes care of the valid authorization for the user account
|
||||
* The {@link AccountHandler} acts as Bridge between MercedesMe Account and the associated vehicles
|
||||
*
|
||||
* @author Bernd Weymann - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class AccountHandler extends BaseBridgeHandler implements AccessTokenRefreshListener {
|
||||
private static final String FEATURE_APPENDIX = "-features";
|
||||
private static final String COMMAND_APPENDIX = "-commands";
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(AccountHandler.class);
|
||||
private final OAuthFactory oAuthFactory;
|
||||
private final NetworkAddressService networkService;
|
||||
private final MercedesMeDiscoveryService discoveryService;
|
||||
private final HttpClient httpClient;
|
||||
private Optional<CallbackServer> server = Optional.empty();
|
||||
private final LocaleProvider localeProvider;
|
||||
private final Storage<String> storage;
|
||||
private final Map<String, VehicleHandler> activeVehicleHandlerMap = new HashMap<>();
|
||||
private final Map<String, VEPUpdate> vepUpdateMap = new HashMap<>();
|
||||
private final Map<String, Map<String, Object>> capabilitiesMap = new HashMap<>();
|
||||
|
||||
private Optional<AuthServer> server = Optional.empty();
|
||||
private Optional<AuthService> authService = Optional.empty();
|
||||
private Optional<ScheduledFuture<?>> scheduledFuture = Optional.empty();
|
||||
|
||||
private String capabilitiesEndpoint = "/v1/vehicle/%s/capabilities";
|
||||
private String commandCapabilitiesEndpoint = "/v1/vehicle/%s/capabilities/commands";
|
||||
private String poiEndpoint = "/v1/vehicle/%s/route";
|
||||
|
||||
final MBWebsocket ws;
|
||||
Optional<AccountConfiguration> config = Optional.empty();
|
||||
@Nullable
|
||||
ClientMessage message;
|
||||
|
||||
public AccountHandler(Bridge bridge, HttpClient hc, OAuthFactory oaf) {
|
||||
public AccountHandler(Bridge bridge, MercedesMeDiscoveryService mmds, HttpClient hc, LocaleProvider lp,
|
||||
StorageService store, NetworkAddressService nas) {
|
||||
super(bridge);
|
||||
discoveryService = mmds;
|
||||
networkService = nas;
|
||||
ws = new MBWebsocket(this);
|
||||
httpClient = hc;
|
||||
oAuthFactory = oaf;
|
||||
localeProvider = lp;
|
||||
storage = store.getStorage(Constants.BINDING_ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
// no commands available
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
updateStatus(ThingStatus.UNKNOWN);
|
||||
config = Optional.of(getConfigAs(AccountConfiguration.class));
|
||||
autodetectCallback();
|
||||
String configValidReason = configValid();
|
||||
@ -69,18 +119,40 @@ public class AccountHandler extends BaseBridgeHandler implements AccessTokenRefr
|
||||
} else {
|
||||
String callbackUrl = Utils.getCallbackAddress(config.get().callbackIP, config.get().callbackPort);
|
||||
thing.setProperty("callbackUrl", callbackUrl);
|
||||
server = Optional.of(new CallbackServer(this, httpClient, oAuthFactory, config.get(), callbackUrl));
|
||||
server = Optional.of(new AuthServer(httpClient, config.get(), callbackUrl));
|
||||
authService = Optional
|
||||
.of(new AuthService(this, httpClient, config.get(), localeProvider.getLocale(), storage));
|
||||
if (!server.get().start()) {
|
||||
String textKey = Constants.STATUS_TEXT_PREFIX + thing.getThingTypeUID().getId()
|
||||
+ Constants.STATUS_SERVER_RESTART;
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.NONE, textKey);
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.NONE,
|
||||
textKey + " [\"" + thing.getProperties().get("callbackUrl") + "\"]");
|
||||
} else {
|
||||
// get fresh token
|
||||
this.getToken();
|
||||
scheduledFuture = Optional.of(scheduler.scheduleWithFixedDelay(this::update, 0,
|
||||
config.get().refreshInterval, TimeUnit.MINUTES));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void update() {
|
||||
if (server.isPresent()) {
|
||||
if (!Constants.NOT_SET.equals(authService.get().getToken())) {
|
||||
ws.run();
|
||||
} else {
|
||||
// all failed - start manual authorization
|
||||
String textKey = Constants.STATUS_TEXT_PREFIX + thing.getThingTypeUID().getId()
|
||||
+ Constants.STATUS_AUTH_NEEDED;
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
textKey + " [\"" + thing.getProperties().get("callbackUrl") + "\"]");
|
||||
}
|
||||
} else {
|
||||
// server not running - fix first
|
||||
String textKey = Constants.STATUS_TEXT_PREFIX + thing.getThingTypeUID().getId()
|
||||
+ Constants.STATUS_SERVER_RESTART;
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.HANDLER_INITIALIZING_ERROR, textKey);
|
||||
}
|
||||
}
|
||||
|
||||
private void autodetectCallback() {
|
||||
// if Callback IP and Callback Port are not set => autodetect these values
|
||||
config = Optional.of(getConfigAs(AccountConfiguration.class));
|
||||
@ -91,12 +163,12 @@ public class AccountHandler extends BaseBridgeHandler implements AccessTokenRefr
|
||||
Utils.addPort(config.get().callbackPort);
|
||||
}
|
||||
if (!updateConfig.containsKey("callbackIP")) {
|
||||
String ip;
|
||||
try {
|
||||
ip = Utils.getCallbackIP();
|
||||
String ip = networkService.getPrimaryIpv4HostAddress();
|
||||
if (ip != null) {
|
||||
updateConfig.put("callbackIP", ip);
|
||||
} catch (SocketException e) {
|
||||
logger.info("Cannot detect IP address {}", e.getMessage());
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.NONE,
|
||||
"@text/mercedesme.account.status.ip-autodetect-failure");
|
||||
}
|
||||
}
|
||||
super.updateConfiguration(updateConfig);
|
||||
@ -107,14 +179,16 @@ public class AccountHandler extends BaseBridgeHandler implements AccessTokenRefr
|
||||
private String configValid() {
|
||||
config = Optional.of(getConfigAs(AccountConfiguration.class));
|
||||
String textKey = Constants.STATUS_TEXT_PREFIX + thing.getThingTypeUID().getId();
|
||||
if (config.get().callbackIP.equals(Constants.NOT_SET)) {
|
||||
if (Constants.NOT_SET.equals(config.get().callbackIP)) {
|
||||
return textKey + Constants.STATUS_IP_MISSING;
|
||||
} else if (config.get().callbackPort == -1) {
|
||||
return textKey + Constants.STATUS_PORT_MISSING;
|
||||
} else if (config.get().clientId.equals(Constants.NOT_SET)) {
|
||||
return textKey + Constants.STATUS_CLIENT_ID_MISSING;
|
||||
} else if (config.get().clientSecret.equals(Constants.NOT_SET)) {
|
||||
return textKey + Constants.STATUS_CLIENT_SECRET_MISSING;
|
||||
} else if (Constants.NOT_SET.equals(config.get().email)) {
|
||||
return textKey + Constants.STATUS_EMAIL_MISSING;
|
||||
} else if (Constants.NOT_SET.equals(config.get().region)) {
|
||||
return textKey + Constants.STATUS_REGION_MISSING;
|
||||
} else if (config.get().refreshInterval <= 01) {
|
||||
return textKey + Constants.STATUS_REFRESH_INVALID;
|
||||
} else {
|
||||
return Constants.EMPTY;
|
||||
}
|
||||
@ -123,18 +197,18 @@ public class AccountHandler extends BaseBridgeHandler implements AccessTokenRefr
|
||||
@Override
|
||||
public void dispose() {
|
||||
if (server.isPresent()) {
|
||||
CallbackServer serv = server.get();
|
||||
serv.stop();
|
||||
serv.dispose();
|
||||
AuthServer authServer = server.get();
|
||||
authServer.stop();
|
||||
authServer.dispose();
|
||||
server = Optional.empty();
|
||||
Utils.removePort(config.get().callbackPort);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleRemoval() {
|
||||
server.ifPresent(s -> s.deleteOAuthServiceAndAccessToken());
|
||||
super.handleRemoval();
|
||||
ws.interrupt();
|
||||
scheduledFuture.ifPresent(schedule -> {
|
||||
if (!schedule.isCancelled()) {
|
||||
schedule.cancel(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@ -142,9 +216,8 @@ public class AccountHandler extends BaseBridgeHandler implements AccessTokenRefr
|
||||
*/
|
||||
@Override
|
||||
public void onAccessTokenResponse(AccessTokenResponse tokenResponse) {
|
||||
if (!tokenResponse.getAccessToken().isEmpty()) {
|
||||
// token not empty - fine
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
if (!Constants.NOT_SET.equals(tokenResponse.getAccessToken())) {
|
||||
scheduler.schedule(this::update, 2, TimeUnit.SECONDS);
|
||||
} else if (server.isEmpty()) {
|
||||
// server not running - fix first
|
||||
String textKey = Constants.STATUS_TEXT_PREFIX + thing.getThingTypeUID().getId()
|
||||
@ -159,16 +232,240 @@ public class AccountHandler extends BaseBridgeHandler implements AccessTokenRefr
|
||||
}
|
||||
}
|
||||
|
||||
public String getToken() {
|
||||
return server.get().getToken();
|
||||
}
|
||||
|
||||
public String getImageApiKey() {
|
||||
return config.get().imageApiKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return Integer.toString(config.get().callbackPort);
|
||||
}
|
||||
|
||||
public String getWSUri() {
|
||||
return Utils.getWebsocketServer(config.get().region);
|
||||
}
|
||||
|
||||
public ClientUpgradeRequest getClientUpgradeRequest() {
|
||||
ClientUpgradeRequest request = new ClientUpgradeRequest();
|
||||
request.setHeader("Authorization", authService.get().getToken());
|
||||
request.setHeader("X-SessionId", UUID.randomUUID().toString());
|
||||
request.setHeader("X-TrackingId", UUID.randomUUID().toString());
|
||||
request.setHeader("Ris-Os-Name", Constants.RIS_OS_NAME);
|
||||
request.setHeader("Ris-Os-Version", Constants.RIS_OS_VERSION);
|
||||
request.setHeader("Ris-Sdk-Version", Utils.getRisSDKVersion(config.get().region));
|
||||
request.setHeader("X-Locale",
|
||||
localeProvider.getLocale().getLanguage() + "-" + localeProvider.getLocale().getCountry()); // de-DE
|
||||
request.setHeader("User-Agent", Utils.getApplication(config.get().region));
|
||||
request.setHeader("X-Applicationname", Utils.getUserAgent(config.get().region));
|
||||
request.setHeader("Ris-Application-Version", Utils.getRisApplicationVersion(config.get().region));
|
||||
return request;
|
||||
}
|
||||
|
||||
public void registerVin(String vin, VehicleHandler handler) {
|
||||
discoveryService.vehicleRemove(this, vin, handler.getThing().getThingTypeUID().getId());
|
||||
activeVehicleHandlerMap.put(vin, handler);
|
||||
VEPUpdate updateForVin = vepUpdateMap.get(vin);
|
||||
if (updateForVin != null) {
|
||||
handler.distributeContent(updateForVin);
|
||||
}
|
||||
}
|
||||
|
||||
public void unregisterVin(String vin) {
|
||||
activeVehicleHandlerMap.remove(vin);
|
||||
}
|
||||
|
||||
@SuppressWarnings("null")
|
||||
public void getVehicleCapabilities(String vin) {
|
||||
if (storage.containsKey(vin + FEATURE_APPENDIX)) {
|
||||
if (activeVehicleHandlerMap.containsKey(vin)) {
|
||||
activeVehicleHandlerMap.get(vin).setFeatureCapabilities(storage.get(vin + FEATURE_APPENDIX));
|
||||
}
|
||||
}
|
||||
if (storage.containsKey(vin + COMMAND_APPENDIX)) {
|
||||
if (activeVehicleHandlerMap.containsKey(vin)) {
|
||||
activeVehicleHandlerMap.get(vin).setCommandCapabilities(storage.get(vin + COMMAND_APPENDIX));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean distributeVepUpdates(Map<String, VEPUpdate> map) {
|
||||
List<String> notFoundList = new ArrayList<>();
|
||||
map.forEach((key, value) -> {
|
||||
VehicleHandler h = activeVehicleHandlerMap.get(key);
|
||||
if (h != null) {
|
||||
h.distributeContent(value);
|
||||
} else {
|
||||
if (value.getFullUpdate()) {
|
||||
vepUpdateMap.put(key, value);
|
||||
}
|
||||
notFoundList.add(key);
|
||||
}
|
||||
});
|
||||
notFoundList.forEach(vin -> {
|
||||
logger.trace("No VehicleHandler available for VIN {}", vin);
|
||||
});
|
||||
return notFoundList.isEmpty();
|
||||
}
|
||||
|
||||
public void commandStatusUpdate(Map<String, AppTwinCommandStatusUpdatesByPID> updatesByVinMap) {
|
||||
updatesByVinMap.forEach((key, value) -> {
|
||||
VehicleHandler h = activeVehicleHandlerMap.get(key);
|
||||
if (h != null) {
|
||||
h.distributeCommandStatus(value);
|
||||
} else {
|
||||
logger.trace("No VehicleHandler available for VIN {}", key);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@SuppressWarnings("null")
|
||||
public void discovery(String vin) {
|
||||
if (activeVehicleHandlerMap.containsKey(vin)) {
|
||||
VehicleHandler vh = activeVehicleHandlerMap.get(vin);
|
||||
if (vh.getThing().getProperties().isEmpty()) {
|
||||
vh.getThing().setProperties(getStringCapabilities(vin));
|
||||
}
|
||||
} else {
|
||||
if (!capabilitiesMap.containsKey(vin)) {
|
||||
// only report new discovery if capabilities aren't discovered yet
|
||||
discoveryService.vehicleDiscovered(this, vin, getCapabilities(vin));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, String> getStringCapabilities(String vin) {
|
||||
Map<String, Object> props = getCapabilities(vin);
|
||||
Map<String, String> stringProps = new HashMap<>();
|
||||
props.forEach((key, value) -> {
|
||||
stringProps.put(key, value.toString());
|
||||
});
|
||||
return stringProps;
|
||||
}
|
||||
|
||||
private Map<String, Object> getCapabilities(String vin) {
|
||||
// check cache before hammering API
|
||||
Map<String, Object> m = capabilitiesMap.get(vin);
|
||||
if (m != null) {
|
||||
return m;
|
||||
}
|
||||
Map<String, Object> featureMap = new HashMap<>();
|
||||
try {
|
||||
// add vehicle capabilities
|
||||
String capabilitiesUrl = Utils.getRestAPIServer(config.get().region)
|
||||
+ String.format(capabilitiesEndpoint, vin);
|
||||
Request capabilitiesRequest = httpClient.newRequest(capabilitiesUrl);
|
||||
authService.get().addBasicHeaders(capabilitiesRequest);
|
||||
capabilitiesRequest.header("X-SessionId", UUID.randomUUID().toString());
|
||||
capabilitiesRequest.header("X-TrackingId", UUID.randomUUID().toString());
|
||||
capabilitiesRequest.header("Authorization", authService.get().getToken());
|
||||
|
||||
ContentResponse capabilitiesResponse = capabilitiesRequest
|
||||
.timeout(Constants.REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS).send();
|
||||
|
||||
String featureCapabilitiesJsonString = capabilitiesResponse.getContentAsString();
|
||||
if (!storage.containsKey(vin + FEATURE_APPENDIX)) {
|
||||
storage.put(vin + FEATURE_APPENDIX, featureCapabilitiesJsonString);
|
||||
}
|
||||
|
||||
JSONObject jsonResponse = new JSONObject(featureCapabilitiesJsonString);
|
||||
JSONObject features = jsonResponse.getJSONObject("features");
|
||||
features.keySet().forEach(key -> {
|
||||
String value = features.get(key).toString();
|
||||
String newKey = Character.toUpperCase(key.charAt(0)) + key.substring(1);
|
||||
newKey = "feature" + newKey;
|
||||
featureMap.put(newKey, value);
|
||||
});
|
||||
|
||||
// get vehicle type
|
||||
JSONObject vehicle = jsonResponse.getJSONObject("vehicle");
|
||||
JSONArray fuelTypes = vehicle.getJSONArray("fuelTypes");
|
||||
if (fuelTypes.length() > 1) {
|
||||
featureMap.put("vehicle", Constants.HYBRID);
|
||||
} else if ("ELECTRIC".equals(fuelTypes.get(0))) {
|
||||
featureMap.put("vehicle", Constants.BEV);
|
||||
} else {
|
||||
featureMap.put("vehicle", Constants.COMBUSTION);
|
||||
}
|
||||
|
||||
// add command capabilities
|
||||
String commandCapabilitiesUrl = Utils.getRestAPIServer(config.get().region)
|
||||
+ String.format(commandCapabilitiesEndpoint, vin);
|
||||
Request commandCapabilitiesRequest = httpClient.newRequest(commandCapabilitiesUrl);
|
||||
authService.get().addBasicHeaders(commandCapabilitiesRequest);
|
||||
commandCapabilitiesRequest.header("X-SessionId", UUID.randomUUID().toString());
|
||||
commandCapabilitiesRequest.header("X-TrackingId", UUID.randomUUID().toString());
|
||||
commandCapabilitiesRequest.header("Authorization", authService.get().getToken());
|
||||
ContentResponse commandCapabilitiesResponse = commandCapabilitiesRequest
|
||||
.timeout(Constants.REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS).send();
|
||||
|
||||
String commandCapabilitiesJsonString = commandCapabilitiesResponse.getContentAsString();
|
||||
if (!storage.containsKey(vin + COMMAND_APPENDIX)) {
|
||||
storage.put(vin + COMMAND_APPENDIX, commandCapabilitiesJsonString);
|
||||
}
|
||||
JSONObject commands = new JSONObject(commandCapabilitiesJsonString);
|
||||
JSONArray commandArray = commands.getJSONArray("commands");
|
||||
commandArray.forEach(object -> {
|
||||
String commandName = ((JSONObject) object).get("commandName").toString();
|
||||
String[] words = commandName.split("[\\W_]+");
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("command");
|
||||
for (int i = 0; i < words.length; i++) {
|
||||
String word = words[i];
|
||||
word = word.isEmpty() ? word
|
||||
: Character.toUpperCase(word.charAt(0)) + word.substring(1).toLowerCase();
|
||||
builder.append(word);
|
||||
}
|
||||
String value = ((JSONObject) object).get("isAvailable").toString();
|
||||
featureMap.put(builder.toString(), value);
|
||||
});
|
||||
// store in cache
|
||||
capabilitiesMap.put(vin, featureMap);
|
||||
return featureMap;
|
||||
} catch (InterruptedException | TimeoutException | ExecutionException e) {
|
||||
logger.trace("Error retrieving capabilities: {}", e.getMessage());
|
||||
featureMap.clear();
|
||||
}
|
||||
return featureMap;
|
||||
}
|
||||
|
||||
public void sendCommand(@Nullable ClientMessage cm) {
|
||||
if (cm != null) {
|
||||
ws.setCommand(cm);
|
||||
}
|
||||
scheduler.schedule(this::update, 2, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
public void keepAlive(boolean b) {
|
||||
ws.keepAlive(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateStatus(ThingStatus ts) {
|
||||
super.updateStatus(ts);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateStatus(ThingStatus ts, ThingStatusDetail tsd, @Nullable String tsdt) {
|
||||
super.updateStatus(ts, tsd, tsdt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Vehicle Actions
|
||||
*
|
||||
* @param poi
|
||||
*/
|
||||
|
||||
public void sendPoi(String vin, JSONObject poi) {
|
||||
String poiUrl = Utils.getRestAPIServer(config.get().region) + String.format(poiEndpoint, vin);
|
||||
Request poiRequest = httpClient.POST(poiUrl);
|
||||
authService.get().addBasicHeaders(poiRequest);
|
||||
poiRequest.header("X-SessionId", UUID.randomUUID().toString());
|
||||
poiRequest.header("X-TrackingId", UUID.randomUUID().toString());
|
||||
poiRequest.header("Authorization", authService.get().getToken());
|
||||
poiRequest.header(HttpHeader.CONTENT_TYPE, "application/json");
|
||||
poiRequest.content(new StringContentProvider(poi.toString(), "utf-8"));
|
||||
|
||||
try {
|
||||
ContentResponse cr = poiRequest.timeout(Constants.REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS).send();
|
||||
logger.trace("Send POI Response {} : {}", cr.getStatus(), cr.getContentAsString());
|
||||
} catch (InterruptedException | TimeoutException | ExecutionException e) {
|
||||
logger.trace("Error Sending POI {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,106 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.mercedesme.internal.server;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.eclipse.jetty.server.Connector;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.ServerConnector;
|
||||
import org.eclipse.jetty.servlet.ServletHandler;
|
||||
import org.openhab.binding.mercedesme.internal.Constants;
|
||||
import org.openhab.binding.mercedesme.internal.config.AccountConfiguration;
|
||||
import org.openhab.core.auth.client.oauth2.AccessTokenResponse;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* {@link AuthServer} provides HTTP Server to show servlet content of the authentication process
|
||||
*
|
||||
* @author Bernd Weymann - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class AuthServer {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(AuthServer.class);
|
||||
private static final Map<Integer, AuthServer> SERVER_MAP = new HashMap<>();
|
||||
private static final AccessTokenResponse INVALID_ACCESS_TOKEN = new AccessTokenResponse();
|
||||
|
||||
private final HttpClient httpClient;
|
||||
|
||||
private Optional<Server> server = Optional.empty();
|
||||
private AccountConfiguration config;
|
||||
public String callbackUrl;
|
||||
|
||||
public AuthServer(HttpClient hc, AccountConfiguration config, String callbackUrl) {
|
||||
httpClient = hc;
|
||||
SERVER_MAP.put(Integer.valueOf(config.callbackPort), this);
|
||||
this.config = config;
|
||||
this.callbackUrl = callbackUrl;
|
||||
INVALID_ACCESS_TOKEN.setAccessToken(Constants.EMPTY);
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
SERVER_MAP.remove(Integer.valueOf(config.callbackPort));
|
||||
}
|
||||
|
||||
public boolean start() {
|
||||
// avoid real server start for unit tests
|
||||
if (server.isPresent() || Constants.JUNIT_SERVER_ADDR.equals(callbackUrl)) {
|
||||
return true;
|
||||
}
|
||||
server = Optional.of(new Server());
|
||||
ServerConnector connector = new ServerConnector(server.get());
|
||||
connector.setPort(config.callbackPort);
|
||||
server.get().setConnectors(new Connector[] { connector });
|
||||
ServletHandler servletHandler = new ServletHandler();
|
||||
server.get().setHandler(servletHandler);
|
||||
servletHandler.addServletWithMapping(AuthServlet.class, Constants.CALLBACK_ENDPOINT);
|
||||
try {
|
||||
server.get().start();
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
LOGGER.trace("Cannot start Callback Server for port {}, Error {}", config.callbackPort, e.getMessage());
|
||||
server = Optional.empty();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
try {
|
||||
if (server.isPresent()) {
|
||||
server.get().stop();
|
||||
server = Optional.empty();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOGGER.trace("Cannot start Callback Server for port {}, Error {}", config.callbackPort, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static AuthServer getServer(int port) {
|
||||
return SERVER_MAP.get(port);
|
||||
}
|
||||
|
||||
public HttpClient getHttpClient() {
|
||||
return httpClient;
|
||||
}
|
||||
|
||||
public String getRegion() {
|
||||
return config.region;
|
||||
}
|
||||
}
|
@ -0,0 +1,274 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.mercedesme.internal.server;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.Instant;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.eclipse.jetty.client.api.ContentResponse;
|
||||
import org.eclipse.jetty.client.api.Request;
|
||||
import org.eclipse.jetty.client.util.StringContentProvider;
|
||||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.openhab.binding.mercedesme.internal.Constants;
|
||||
import org.openhab.binding.mercedesme.internal.config.AccountConfiguration;
|
||||
import org.openhab.binding.mercedesme.internal.dto.PINRequest;
|
||||
import org.openhab.binding.mercedesme.internal.dto.TokenResponse;
|
||||
import org.openhab.binding.mercedesme.internal.utils.Utils;
|
||||
import org.openhab.core.auth.client.oauth2.AccessTokenRefreshListener;
|
||||
import org.openhab.core.auth.client.oauth2.AccessTokenResponse;
|
||||
import org.openhab.core.storage.Storage;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* {@link AuthService} helpers for token management
|
||||
*
|
||||
* @author Bernd Weymann - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class AuthService {
|
||||
public static final AccessTokenResponse INVALID_TOKEN = new AccessTokenResponse();
|
||||
private static final int EXPIRATION_BUFFER = 5;
|
||||
private static final Map<Integer, AuthService> AUTH_MAP = new HashMap<>();
|
||||
private final Logger logger = LoggerFactory.getLogger(AuthService.class);
|
||||
|
||||
AccessTokenRefreshListener listener;
|
||||
private HttpClient httpClient;
|
||||
private String identifier;
|
||||
private AccountConfiguration config;
|
||||
private Locale locale;
|
||||
private Storage<String> storage;
|
||||
private AccessTokenResponse token;
|
||||
|
||||
public AuthService(AccessTokenRefreshListener atrl, HttpClient hc, AccountConfiguration ac, Locale l,
|
||||
Storage<String> store) {
|
||||
INVALID_TOKEN.setAccessToken(Constants.NOT_SET);
|
||||
INVALID_TOKEN.setRefreshToken(Constants.NOT_SET);
|
||||
listener = atrl;
|
||||
httpClient = hc;
|
||||
config = ac;
|
||||
identifier = config.email;
|
||||
locale = l;
|
||||
storage = store;
|
||||
|
||||
// restore token
|
||||
String storedObject = storage.get(identifier);
|
||||
if (storedObject == null) {
|
||||
token = INVALID_TOKEN;
|
||||
listener.onAccessTokenResponse(token);
|
||||
} else {
|
||||
token = Utils.fromString(storedObject);
|
||||
if (token.isExpired(Instant.now(), EXPIRATION_BUFFER)) {
|
||||
if (!Constants.NOT_SET.equals(token.getRefreshToken())) {
|
||||
refreshToken();
|
||||
listener.onAccessTokenResponse(token);
|
||||
} else {
|
||||
token = INVALID_TOKEN;
|
||||
listener.onAccessTokenResponse(token);
|
||||
}
|
||||
} else {
|
||||
listener.onAccessTokenResponse(token);
|
||||
}
|
||||
}
|
||||
AUTH_MAP.put(config.callbackPort, this);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static AuthService getAuthService(Integer key) {
|
||||
return AUTH_MAP.get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return guid from request to create token in next step
|
||||
*/
|
||||
public String requestPin() {
|
||||
String configUrl = Utils.getAuthConfigURL(config.region);
|
||||
String sessionId = UUID.randomUUID().toString();
|
||||
Request configRequest = httpClient.newRequest(configUrl);
|
||||
addBasicHeaders(configRequest);
|
||||
configRequest.header("X-Trackingid", UUID.randomUUID().toString());
|
||||
configRequest.header("X-Sessionid", sessionId);
|
||||
try {
|
||||
ContentResponse cr = configRequest.timeout(Constants.REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS).send();
|
||||
if (cr.getStatus() == 200) {
|
||||
logger.trace("{} Config Request PIN fine {} {}", prefix(), cr.getStatus(), cr.getContentAsString());
|
||||
} else {
|
||||
logger.trace("{} Failed to request config for pin {} {}", prefix(), cr.getStatus(),
|
||||
cr.getContentAsString());
|
||||
return Constants.NOT_SET;
|
||||
}
|
||||
} catch (InterruptedException | TimeoutException | ExecutionException e) {
|
||||
logger.trace("{} Failed to request config for pin {}", prefix(), e.getMessage());
|
||||
return Constants.NOT_SET;
|
||||
}
|
||||
|
||||
String url = Utils.getAuthURL(config.region);
|
||||
Request req = httpClient.POST(url);
|
||||
addBasicHeaders(req);
|
||||
req.header("X-Trackingid", UUID.randomUUID().toString());
|
||||
req.header("X-Sessionid", sessionId);
|
||||
|
||||
PINRequest pr = new PINRequest(config.email, locale.getCountry());
|
||||
req.header(HttpHeader.CONTENT_TYPE, "application/json");
|
||||
logger.trace("{} payload {}", url, Utils.GSON.toJson(pr));
|
||||
req.content(new StringContentProvider(Utils.GSON.toJson(pr), "utf-8"));
|
||||
|
||||
try {
|
||||
ContentResponse cr = req.timeout(Constants.REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS).send();
|
||||
if (cr.getStatus() == 200) {
|
||||
logger.trace("{} Request PIN fine {} {}", prefix(), cr.getStatus(), cr.getContentAsString());
|
||||
return pr.nonce;
|
||||
} else {
|
||||
logger.trace("{} Failed to request pin {} {}", prefix(), cr.getStatus(), cr.getContentAsString());
|
||||
}
|
||||
} catch (InterruptedException | TimeoutException | ExecutionException e) {
|
||||
logger.trace("{} Failed to request pin {}", prefix(), e.getMessage());
|
||||
}
|
||||
return Constants.NOT_SET;
|
||||
}
|
||||
|
||||
public boolean requestToken(String password) {
|
||||
try {
|
||||
// Request + headers
|
||||
String url = Utils.getTokenUrl(config.region);
|
||||
Request req = httpClient.POST(url);
|
||||
addBasicHeaders(req);
|
||||
req.header("Stage", "prod");
|
||||
req.header("X-Device-Id", UUID.randomUUID().toString());
|
||||
req.header("X-Request-Id", UUID.randomUUID().toString());
|
||||
|
||||
// Content URL form
|
||||
String clientId = "client_id="
|
||||
+ URLEncoder.encode(Utils.getLoginAppId(config.region), StandardCharsets.UTF_8.toString());
|
||||
String grantAttribute = "grant_type=password";
|
||||
String userAttribute = "username=" + URLEncoder.encode(config.email, StandardCharsets.UTF_8.toString());
|
||||
String passwordAttribute = "password=" + URLEncoder.encode(password, StandardCharsets.UTF_8.toString());
|
||||
String scopeAttribute = "scope=" + URLEncoder.encode(Constants.SCOPE, StandardCharsets.UTF_8.toString());
|
||||
String content = clientId + "&" + grantAttribute + "&" + userAttribute + "&" + passwordAttribute + "&"
|
||||
+ scopeAttribute;
|
||||
req.header(HttpHeader.CONTENT_TYPE, "application/x-www-form-urlencoded");
|
||||
req.content(new StringContentProvider(content));
|
||||
|
||||
// Send
|
||||
ContentResponse cr = req.timeout(Constants.REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS).send();
|
||||
if (cr.getStatus() == 200) {
|
||||
String responseString = cr.getContentAsString();
|
||||
saveTokenResponse(responseString);
|
||||
listener.onAccessTokenResponse(token);
|
||||
return true;
|
||||
} else {
|
||||
logger.trace("{} Failed to get token {} {}", prefix(), cr.getStatus(), cr.getContentAsString());
|
||||
}
|
||||
} catch (InterruptedException | TimeoutException | ExecutionException | UnsupportedEncodingException e) {
|
||||
logger.trace("{} Failed to get token {}", prefix(), e.getMessage());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void refreshToken() {
|
||||
try {
|
||||
String url = Utils.getTokenUrl(config.region);
|
||||
Request req = httpClient.POST(url);
|
||||
req.header("X-Device-Id", UUID.randomUUID().toString());
|
||||
req.header("X-Request-Id", UUID.randomUUID().toString());
|
||||
|
||||
// Content URL form
|
||||
String grantAttribute = "grant_type=refresh_token";
|
||||
String refreshTokenAttribute = "refresh_token="
|
||||
+ URLEncoder.encode(token.getRefreshToken(), StandardCharsets.UTF_8.toString());
|
||||
String content = grantAttribute + "&" + refreshTokenAttribute;
|
||||
req.header(HttpHeader.CONTENT_TYPE, "application/x-www-form-urlencoded");
|
||||
req.content(new StringContentProvider(content));
|
||||
|
||||
// Send
|
||||
ContentResponse cr = req.timeout(Constants.REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS).send();
|
||||
if (cr.getStatus() == 200) {
|
||||
saveTokenResponse(cr.getContentAsString());
|
||||
listener.onAccessTokenResponse(token);
|
||||
} else {
|
||||
logger.trace("{} Failed to refresh token {} {}", prefix(), cr.getStatus(), cr.getContentAsString());
|
||||
}
|
||||
} catch (InterruptedException | TimeoutException | ExecutionException | UnsupportedEncodingException e) {
|
||||
logger.trace("{} Failed to refresh token {}", prefix(), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public String getToken() {
|
||||
if (token.isExpired(Instant.now(), EXPIRATION_BUFFER)) {
|
||||
if (!Constants.NOT_SET.equals(token.getRefreshToken())) {
|
||||
refreshToken();
|
||||
// token shall be updated now - retry expired check
|
||||
if (token.isExpired(Instant.now(), EXPIRATION_BUFFER)) {
|
||||
token = INVALID_TOKEN;
|
||||
listener.onAccessTokenResponse(token);
|
||||
return Constants.NOT_SET;
|
||||
}
|
||||
} else {
|
||||
token = INVALID_TOKEN;
|
||||
logger.trace("{} Refresh token empty", prefix());
|
||||
}
|
||||
}
|
||||
return token.getAccessToken();
|
||||
}
|
||||
|
||||
public void addBasicHeaders(Request req) {
|
||||
req.header("Ris-Os-Name", Constants.RIS_OS_NAME);
|
||||
req.header("Ris-Os-Version", Constants.RIS_OS_VERSION);
|
||||
req.header("Ris-Sdk-Version", Utils.getRisSDKVersion(config.region));
|
||||
req.header("X-Locale", locale.getLanguage() + "-" + locale.getCountry()); // de-DE
|
||||
req.header("User-Agent", Utils.getApplication(config.region));
|
||||
req.header("X-Applicationname", Utils.getUserAgent(config.region));
|
||||
req.header("Ris-Application-Version", Utils.getRisApplicationVersion(config.region));
|
||||
}
|
||||
|
||||
private void saveTokenResponse(String response) {
|
||||
TokenResponse tr = Utils.GSON.fromJson(response, TokenResponse.class);
|
||||
AccessTokenResponse atr = new AccessTokenResponse();
|
||||
if (tr != null) {
|
||||
atr.setAccessToken(tr.accessToken);
|
||||
atr.setCreatedOn(Instant.now());
|
||||
atr.setExpiresIn(tr.expiresIn);
|
||||
// Preserve refresh token if available
|
||||
if (Constants.NOT_SET.equals(tr.refreshToken) && !Constants.NOT_SET.equals(token.getRefreshToken())) {
|
||||
atr.setRefreshToken(token.getRefreshToken());
|
||||
} else if (!Constants.NOT_SET.equals(tr.refreshToken)) {
|
||||
atr.setRefreshToken(tr.refreshToken);
|
||||
} else {
|
||||
logger.trace("{} Neither new nor old refresh token available", prefix());
|
||||
}
|
||||
atr.setTokenType("Bearer");
|
||||
atr.setScope(Constants.SCOPE);
|
||||
storage.put(identifier, Utils.toString(atr));
|
||||
token = atr;
|
||||
} else {
|
||||
logger.trace("{} Token Response is null", prefix());
|
||||
}
|
||||
}
|
||||
|
||||
private String prefix() {
|
||||
return "[" + config.email + "] ";
|
||||
}
|
||||
}
|
@ -0,0 +1,104 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.mercedesme.internal.server;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.mercedesme.internal.Constants;
|
||||
|
||||
/**
|
||||
* {@link AuthServlet} provides simple HTML pages for authorization workflow
|
||||
*
|
||||
* @author Bernd Weymann - Initial contribution
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
@NonNullByDefault
|
||||
public class AuthServlet extends HttpServlet {
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException {
|
||||
AuthService myAuthService = AuthService.getAuthService(request.getLocalPort());
|
||||
String guid = request.getParameter(Constants.GUID);
|
||||
String pin = request.getParameter(Constants.PIN);
|
||||
if (guid == null && pin == null && myAuthService != null) {
|
||||
// request PIN
|
||||
String requestVal = myAuthService.requestPin();
|
||||
if (!Constants.NOT_SET.equals(requestVal)) {
|
||||
response.setStatus(HttpServletResponse.SC_OK);
|
||||
response.getWriter().println("<HTML>");
|
||||
response.getWriter().println("<BODY>");
|
||||
response.getWriter().println("<H1>Step 1 - PIN Requested</H1>");
|
||||
response.getWriter().println("<BR>");
|
||||
response.getWriter().println("PIN was requested and should be present in your EMail Inbox<BR>");
|
||||
response.getWriter()
|
||||
.println("Check first if you received the PIN and then continue with the below Link<BR>");
|
||||
response.getWriter().println("<a href=\"" + Constants.CALLBACK_ENDPOINT + "?guid=" + requestVal
|
||||
+ "\">Click here to continue with Step 2</a>");
|
||||
response.getWriter().println("</BODY>");
|
||||
response.getWriter().println("</HTML>");
|
||||
} else {
|
||||
response.setStatus(HttpServletResponse.SC_OK);
|
||||
response.getWriter().println("<HTML>");
|
||||
response.getWriter().println("<BODY>");
|
||||
response.getWriter().println("Something went wrong<BR>");
|
||||
response.getWriter().println("</BODY>");
|
||||
response.getWriter().println("</HTML>");
|
||||
}
|
||||
|
||||
} else if (guid != null && pin == null && myAuthService != null) {
|
||||
// show insert PIN input field
|
||||
|
||||
response.setContentType("text/html");
|
||||
response.setStatus(HttpServletResponse.SC_OK);
|
||||
response.getWriter().println("<HTML>");
|
||||
response.getWriter().println("<BODY>");
|
||||
response.getWriter().println("<H1>Step 2 - Enter PIN</H1>");
|
||||
response.getWriter().println("<BR>");
|
||||
response.getWriter().println("Enter PIN in second input field - leave guid as it is!<BR>");
|
||||
response.getWriter().println("<form action=\"" + Constants.CALLBACK_ENDPOINT + "\">");
|
||||
response.getWriter().println("<BR>");
|
||||
response.getWriter().println("<label for=\"GUID\">GUID</label>");
|
||||
response.getWriter().println("<input type=\"text\" id=\"guid\" name=\"guid\" value=\"" + guid + "\">");
|
||||
response.getWriter().println("<BR>");
|
||||
response.getWriter().println("<label for=\"PIN\">PIN</label>");
|
||||
response.getWriter().println("<input type=\"text\" id=\"pin\" name=\"pin\" placeholder=\"Your PIN\">");
|
||||
response.getWriter().println("<BR>");
|
||||
response.getWriter().println("<input type=\"submit\" value=\"Submit\">");
|
||||
response.getWriter().println("</form>");
|
||||
response.getWriter().println("</BODY>");
|
||||
response.getWriter().println("</HTML>");
|
||||
} else if (guid != null && pin != null && myAuthService != null) {
|
||||
// call getToken and show result
|
||||
boolean result = myAuthService.requestToken(guid + ":" + pin);
|
||||
response.setContentType("text/html");
|
||||
response.setStatus(HttpServletResponse.SC_OK);
|
||||
response.getWriter().println("<HTML>");
|
||||
response.getWriter().println("<BODY>");
|
||||
response.getWriter().println("<H1>Step 3 - Save Token</H1>");
|
||||
response.getWriter().println("<BR>");
|
||||
if (result) {
|
||||
response.getWriter().println("Success - everything done!<BR>");
|
||||
} else {
|
||||
response.getWriter().println("Failure - Please check logs for further analysis!<BR>");
|
||||
}
|
||||
response.getWriter().println("</BODY>");
|
||||
response.getWriter().println("</HTML>");
|
||||
}
|
||||
}
|
||||
}
|
@ -1,196 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.mercedesme.internal.server;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.eclipse.jetty.server.Connector;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.ServerConnector;
|
||||
import org.eclipse.jetty.servlet.ServletHandler;
|
||||
import org.openhab.binding.mercedesme.internal.Constants;
|
||||
import org.openhab.binding.mercedesme.internal.config.AccountConfiguration;
|
||||
import org.openhab.core.auth.client.oauth2.AccessTokenRefreshListener;
|
||||
import org.openhab.core.auth.client.oauth2.AccessTokenResponse;
|
||||
import org.openhab.core.auth.client.oauth2.OAuthClientService;
|
||||
import org.openhab.core.auth.client.oauth2.OAuthException;
|
||||
import org.openhab.core.auth.client.oauth2.OAuthFactory;
|
||||
import org.openhab.core.auth.client.oauth2.OAuthResponseException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link CallbackServer} class defines an HTTP Server for authentication callbacks
|
||||
*
|
||||
* @author Bernd Weymann - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class CallbackServer {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(CallbackServer.class);
|
||||
private static final Map<Integer, OAuthClientService> AUTH_MAP = new HashMap<>();
|
||||
private static final Map<Integer, CallbackServer> SERVER_MAP = new HashMap<>();
|
||||
private static final AccessTokenResponse INVALID_ACCESS_TOKEN = new AccessTokenResponse();
|
||||
|
||||
private final OAuthFactory oAuthFactory;
|
||||
|
||||
private Optional<Server> server = Optional.empty();
|
||||
private AccessTokenRefreshListener listener;
|
||||
private AccountConfiguration config;
|
||||
private OAuthClientService oacs;
|
||||
private String callbackUrl;
|
||||
|
||||
public CallbackServer(AccessTokenRefreshListener l, HttpClient hc, OAuthFactory oAuthFactory,
|
||||
AccountConfiguration config, String callbackUrl) {
|
||||
this.oAuthFactory = oAuthFactory;
|
||||
oacs = oAuthFactory.createOAuthClientService(config.clientId, Constants.MB_TOKEN_URL, Constants.MB_AUTH_URL,
|
||||
config.clientId, config.clientSecret, config.getScope(), false);
|
||||
listener = l;
|
||||
AUTH_MAP.put(Integer.valueOf(config.callbackPort), oacs);
|
||||
SERVER_MAP.put(Integer.valueOf(config.callbackPort), this);
|
||||
this.config = config;
|
||||
this.callbackUrl = callbackUrl;
|
||||
INVALID_ACCESS_TOKEN.setAccessToken(Constants.EMPTY);
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
oAuthFactory.ungetOAuthService(config.clientId);
|
||||
AUTH_MAP.remove(Integer.valueOf(config.callbackPort));
|
||||
SERVER_MAP.remove(Integer.valueOf(config.callbackPort));
|
||||
}
|
||||
|
||||
public void deleteOAuthServiceAndAccessToken() {
|
||||
oAuthFactory.deleteServiceAndAccessToken(config.clientId);
|
||||
}
|
||||
|
||||
public String getAuthorizationUrl() {
|
||||
try {
|
||||
return oacs.getAuthorizationUrl(callbackUrl, null, null);
|
||||
} catch (OAuthException e) {
|
||||
LOGGER.warn("Error creating Authorization URL {}", e.getMessage());
|
||||
return Constants.EMPTY;
|
||||
}
|
||||
}
|
||||
|
||||
public String getScope() {
|
||||
return config.getScope();
|
||||
}
|
||||
|
||||
public boolean start() {
|
||||
LOGGER.debug("Start Callback Server for port {}", config.callbackPort);
|
||||
if (server.isPresent()) {
|
||||
LOGGER.debug("Callback server for port {} already started", config.callbackPort);
|
||||
return true;
|
||||
}
|
||||
server = Optional.of(new Server());
|
||||
ServerConnector connector = new ServerConnector(server.get());
|
||||
connector.setPort(config.callbackPort);
|
||||
server.get().setConnectors(new Connector[] { connector });
|
||||
ServletHandler servletHandler = new ServletHandler();
|
||||
server.get().setHandler(servletHandler);
|
||||
servletHandler.addServletWithMapping(CallbackServlet.class, Constants.CALLBACK_ENDPOINT);
|
||||
try {
|
||||
server.get().start();
|
||||
} catch (Exception e) {
|
||||
LOGGER.warn("Cannot start Callback Server for port {}, Error {}", config.callbackPort, e.getMessage());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
LOGGER.debug("Stop Callback Server");
|
||||
try {
|
||||
if (server.isPresent()) {
|
||||
server.get().stop();
|
||||
server = Optional.empty();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOGGER.warn("Cannot start Callback Server for port {}, Error {}", config.callbackPort, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public String getToken() {
|
||||
AccessTokenResponse atr = null;
|
||||
try {
|
||||
/*
|
||||
* this will automatically trigger
|
||||
* - return last stored token if it's still valid
|
||||
* - refreshToken if current token is expired
|
||||
* - inform listeners if refresh delivered new token
|
||||
* - store new token in persistence
|
||||
*/
|
||||
atr = oacs.getAccessTokenResponse();
|
||||
} catch (OAuthException | IOException | OAuthResponseException e) {
|
||||
LOGGER.warn("Exception getting token {}", e.getMessage());
|
||||
}
|
||||
if (atr == null) {
|
||||
LOGGER.debug("Token empty - Manual Authorization needed at {}", callbackUrl);
|
||||
listener.onAccessTokenResponse(INVALID_ACCESS_TOKEN);
|
||||
return INVALID_ACCESS_TOKEN.getAccessToken();
|
||||
}
|
||||
listener.onAccessTokenResponse(atr);
|
||||
return atr.getAccessToken();
|
||||
}
|
||||
|
||||
/**
|
||||
* Static callback for Servlet calls
|
||||
*
|
||||
* @param port
|
||||
* @param code
|
||||
*/
|
||||
public static void callback(int port, String code) {
|
||||
LOGGER.trace("Callback from Servlet {} {}", port, code);
|
||||
try {
|
||||
OAuthClientService oacs = AUTH_MAP.get(port);
|
||||
LOGGER.trace("Get token from code {}", code);
|
||||
// get CallbackServer instance
|
||||
CallbackServer srv = SERVER_MAP.get(port);
|
||||
LOGGER.trace("Deliver token to {}", srv);
|
||||
if (srv != null && oacs != null) {
|
||||
// token stored and persisted inside oacs
|
||||
AccessTokenResponse atr = oacs.getAccessTokenResponseByAuthorizationCode(code, srv.callbackUrl);
|
||||
// inform listener - not done by oacs
|
||||
srv.listener.onAccessTokenResponse(atr);
|
||||
} else {
|
||||
LOGGER.warn("Either Callbackserver {} or Authorization Service {} not found", srv, oacs);
|
||||
}
|
||||
} catch (OAuthException | IOException | OAuthResponseException e) {
|
||||
LOGGER.warn("Exception getting token from code {} {}", code, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public static String getAuthorizationUrl(int port) {
|
||||
CallbackServer srv = SERVER_MAP.get(port);
|
||||
if (srv != null) {
|
||||
return srv.getAuthorizationUrl();
|
||||
} else {
|
||||
LOGGER.debug("No Callbackserver found for {}", port);
|
||||
return Constants.EMPTY;
|
||||
}
|
||||
}
|
||||
|
||||
public static String getScope(int port) {
|
||||
CallbackServer srv = SERVER_MAP.get(port);
|
||||
if (srv != null) {
|
||||
return srv.getScope();
|
||||
} else {
|
||||
LOGGER.debug("No Callbackserver found for {}", port);
|
||||
return Constants.EMPTY;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,73 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.mercedesme.internal.server;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.mercedesme.internal.Constants;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link CallbackServlet} class provides authentication callback endpoint
|
||||
*
|
||||
* @author Bernd Weymann - Initial contribution
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
@NonNullByDefault
|
||||
public class CallbackServlet extends HttpServlet {
|
||||
private final Logger logger = LoggerFactory.getLogger(CallbackServlet.class);
|
||||
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException {
|
||||
String code = request.getParameter(Constants.CODE);
|
||||
if (code != null) {
|
||||
CallbackServer.callback(request.getLocalPort(), code);
|
||||
logger.trace("Code successfully extracted {}", request.getParameterMap());
|
||||
response.setContentType("application/json");
|
||||
response.setStatus(HttpServletResponse.SC_OK);
|
||||
response.getWriter().println(request.getParameterMap());
|
||||
response.getWriter().println("{ \"status\": \"ok\"}");
|
||||
} else {
|
||||
response.setContentType("text/html");
|
||||
response.setStatus(HttpServletResponse.SC_OK);
|
||||
response.getWriter().println("<HTML>");
|
||||
response.getWriter().println("<BODY>");
|
||||
response.getWriter().println("<B>Call Parameters</B>");
|
||||
response.getWriter().println("<BR>");
|
||||
response.getWriter().println(request.getParameterMap());
|
||||
response.getWriter().println("<BR><BR>");
|
||||
response.getWriter().println("<B>Configured scopes</B><BR>");
|
||||
String[] scopes = CallbackServer.getScope(request.getLocalPort()).split(Constants.SPACE);
|
||||
for (int i = 0; i < scopes.length; i++) {
|
||||
response.getWriter().println(scopes[i] + "<BR>");
|
||||
}
|
||||
response.getWriter().println("<BR><BR>");
|
||||
response.getWriter().println("<B>Get your access token for openHAB MercedesMe Binding</B>");
|
||||
response.getWriter().println("<BR>");
|
||||
response.getWriter().println("<a href=\"" + CallbackServer.getAuthorizationUrl(request.getLocalPort())
|
||||
+ "\">Start Authorization</a>");
|
||||
response.getWriter().println("</BODY>");
|
||||
response.getWriter().println("</HTML>");
|
||||
}
|
||||
logger.debug("Call from {}:{} parameters {}", request.getLocalAddr(), request.getLocalPort(),
|
||||
request.getParameterMap());
|
||||
}
|
||||
}
|
@ -0,0 +1,265 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.mercedesme.internal.server;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.eclipse.jetty.websocket.api.Session;
|
||||
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
|
||||
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
|
||||
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketError;
|
||||
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
|
||||
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
|
||||
import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.client.WebSocketClient;
|
||||
import org.openhab.binding.mercedesme.internal.Constants;
|
||||
import org.openhab.binding.mercedesme.internal.handler.AccountHandler;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.ThingStatusDetail;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.daimler.mbcarkit.proto.Client.ClientMessage;
|
||||
import com.daimler.mbcarkit.proto.Protos.AcknowledgeAssignedVehicles;
|
||||
import com.daimler.mbcarkit.proto.VehicleEvents;
|
||||
import com.daimler.mbcarkit.proto.VehicleEvents.AcknowledgeVEPUpdatesByVIN;
|
||||
import com.daimler.mbcarkit.proto.VehicleEvents.PushMessage;
|
||||
import com.daimler.mbcarkit.proto.Vehicleapi.AcknowledgeAppTwinCommandStatusUpdatesByVIN;
|
||||
import com.daimler.mbcarkit.proto.Vehicleapi.AppTwinCommandStatusUpdatesByVIN;
|
||||
|
||||
/**
|
||||
* {@link MBWebsocket} as socket endpoint to communicate with Mercedes
|
||||
*
|
||||
* @author Bernd Weymann - Initial contribution
|
||||
*/
|
||||
@WebSocket
|
||||
@NonNullByDefault
|
||||
public class MBWebsocket {
|
||||
// timeout 14 Minutes - just below scheduling of 15 Minutes by AccountHandler
|
||||
private static final int CONNECT_TIMEOUT_MS = 14 * 60 * 1000;
|
||||
// standard runtime of Websocket
|
||||
private static final int WS_RUNTIME_MS = 60 * 1000;
|
||||
// addon time of 1 minute for a new send command
|
||||
private static final int ADDON_MESSAGE_TIME_MS = 60 * 1000;
|
||||
// check Socket time elapsed each second
|
||||
private static final int CHECK_INTERVAL_MS = 1000;
|
||||
// additional 5 minutes after keep alive
|
||||
private static final int KEEP_ALIVE_ADDON = 5 * 60 * 1000;
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(MBWebsocket.class);
|
||||
private AccountHandler accountHandler;
|
||||
private boolean running = false;
|
||||
private Instant runTill = Instant.now();
|
||||
private @Nullable Session session;
|
||||
private List<ClientMessage> commandQueue = new ArrayList<>();
|
||||
|
||||
private boolean keepAlive = false;
|
||||
|
||||
public MBWebsocket(AccountHandler ah) {
|
||||
accountHandler = ah;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is called by
|
||||
* - scheduler every 15 minutes
|
||||
* - handler sending a command
|
||||
* - handler requesting refresh
|
||||
*/
|
||||
public void run() {
|
||||
synchronized (this) {
|
||||
if (running) {
|
||||
return;
|
||||
} else {
|
||||
running = true;
|
||||
runTill = Instant.now().plusMillis(WS_RUNTIME_MS);
|
||||
}
|
||||
}
|
||||
try {
|
||||
WebSocketClient client = new WebSocketClient();
|
||||
client.setMaxIdleTimeout(CONNECT_TIMEOUT_MS);
|
||||
client.setStopTimeout(CONNECT_TIMEOUT_MS);
|
||||
ClientUpgradeRequest request = accountHandler.getClientUpgradeRequest();
|
||||
String websocketURL = accountHandler.getWSUri();
|
||||
logger.trace("Websocket start {}", websocketURL);
|
||||
if (Constants.JUNIT_TOKEN.equals(request.getHeader("Authorization"))) {
|
||||
// avoid unit test requesting real websocket - simply return
|
||||
return;
|
||||
}
|
||||
client.start();
|
||||
client.connect(this, new URI(websocketURL), request);
|
||||
while (keepAlive || Instant.now().isBefore(runTill)) {
|
||||
try {
|
||||
Thread.sleep(CHECK_INTERVAL_MS);
|
||||
} catch (InterruptedException ie) {
|
||||
logger.trace("Websocket interrupted during sleeping - stop executing");
|
||||
runTill = Instant.MIN;
|
||||
}
|
||||
// sends one message per second
|
||||
if (sendMessage()) {
|
||||
// add additional runtime to execute and finish command
|
||||
runTill = runTill.plusMillis(ADDON_MESSAGE_TIME_MS);
|
||||
}
|
||||
}
|
||||
logger.trace("Websocket stop");
|
||||
client.stop();
|
||||
client.destroy();
|
||||
} catch (Throwable t) {
|
||||
// catch Exceptions of start stop and declare communication error
|
||||
accountHandler.updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"@text/mercedesme.account.status.websocket-failure");
|
||||
logger.warn("Websocket handling exception: {}", t.getMessage());
|
||||
}
|
||||
synchronized (this) {
|
||||
running = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void setCommand(ClientMessage cm) {
|
||||
commandQueue.add(cm);
|
||||
}
|
||||
|
||||
private boolean sendMessage() {
|
||||
if (!commandQueue.isEmpty()) {
|
||||
ClientMessage message = commandQueue.remove(0);
|
||||
logger.trace("Send Message {}", message.getAllFields());
|
||||
try {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
message.writeTo(baos);
|
||||
if (session != null) {
|
||||
session.getRemote().sendBytes(ByteBuffer.wrap(baos.toByteArray()));
|
||||
}
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
logger.warn("Error sending message {} : {}", message.getAllFields(), e.getMessage());
|
||||
}
|
||||
logger.info("Send Message {} done", message.getAllFields());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void sendAcknowledgeMessage(ClientMessage message) {
|
||||
try {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
message.writeTo(baos);
|
||||
if (session != null) {
|
||||
session.getRemote().sendBytes(ByteBuffer.wrap(baos.toByteArray()));
|
||||
}
|
||||
} catch (IOException e) {
|
||||
logger.warn("Error sending acknowledge {} : {}", message.getAllFields(), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isRunning() {
|
||||
return running;
|
||||
}
|
||||
|
||||
public void interrupt() {
|
||||
synchronized (this) {
|
||||
runTill = Instant.MIN;
|
||||
keepAlive = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void keepAlive(boolean b) {
|
||||
if (!keepAlive) {
|
||||
if (b) {
|
||||
logger.trace("WebSocket - keep alive start");
|
||||
}
|
||||
} else {
|
||||
if (!b) {
|
||||
// after keep alive is finished add 5 minutes to cover e.g. door events after trip is finished
|
||||
runTill = Instant.now().plusMillis(KEEP_ALIVE_ADDON);
|
||||
logger.trace("Websocket - keep alive stop - run till {}", runTill.toString());
|
||||
}
|
||||
}
|
||||
keepAlive = b;
|
||||
}
|
||||
|
||||
/**
|
||||
* endpoints
|
||||
*/
|
||||
|
||||
@OnWebSocketMessage
|
||||
public void onBytes(InputStream is) {
|
||||
try {
|
||||
PushMessage pm = VehicleEvents.PushMessage.parseFrom(is);
|
||||
if (pm.hasVepUpdates()) {
|
||||
boolean distributed = accountHandler.distributeVepUpdates(pm.getVepUpdates().getUpdatesMap());
|
||||
if (distributed) {
|
||||
AcknowledgeVEPUpdatesByVIN ack = AcknowledgeVEPUpdatesByVIN.newBuilder()
|
||||
.setSequenceNumber(pm.getVepUpdates().getSequenceNumber()).build();
|
||||
ClientMessage cm = ClientMessage.newBuilder().setAcknowledgeVepUpdatesByVin(ack).build();
|
||||
sendAcknowledgeMessage(cm);
|
||||
}
|
||||
} else if (pm.hasAssignedVehicles()) {
|
||||
for (int i = 0; i < pm.getAssignedVehicles().getVinsCount(); i++) {
|
||||
String vin = pm.getAssignedVehicles().getVins(0);
|
||||
accountHandler.discovery(vin);
|
||||
}
|
||||
AcknowledgeAssignedVehicles ack = AcknowledgeAssignedVehicles.newBuilder().build();
|
||||
ClientMessage cm = ClientMessage.newBuilder().setAcknowledgeAssignedVehicles(ack).build();
|
||||
sendAcknowledgeMessage(cm);
|
||||
} else if (pm.hasApptwinCommandStatusUpdatesByVin()) {
|
||||
AppTwinCommandStatusUpdatesByVIN csubv = pm.getApptwinCommandStatusUpdatesByVin();
|
||||
accountHandler.commandStatusUpdate(csubv.getUpdatesByVinMap());
|
||||
AcknowledgeAppTwinCommandStatusUpdatesByVIN ack = AcknowledgeAppTwinCommandStatusUpdatesByVIN
|
||||
.newBuilder().setSequenceNumber(csubv.getSequenceNumber()).build();
|
||||
ClientMessage cm = ClientMessage.newBuilder().setAcknowledgeApptwinCommandStatusUpdateByVin(ack)
|
||||
.build();
|
||||
sendAcknowledgeMessage(cm);
|
||||
} else if (pm.hasApptwinPendingCommandRequest()) {
|
||||
logger.trace("Pending Command {}", pm.getApptwinPendingCommandRequest().getAllFields());
|
||||
} else if (pm.hasDebugMessage()) {
|
||||
logger.trace("MB Debug Message: {}", pm.getDebugMessage().getMessage());
|
||||
} else {
|
||||
logger.trace("MB Message: {} not handled", pm.getAllFields());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// don't report thing status errors here.
|
||||
// Sometimes messages cannot be decoded which doesn't effect the overall functionality
|
||||
logger.trace("IOException {}", e.getMessage());
|
||||
} catch (Error err) {
|
||||
logger.trace("Error caught {}", err.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@OnWebSocketClose
|
||||
public void onDisconnect(Session session, int statusCode, String reason) {
|
||||
logger.debug("Disconnected from server. Status {} Reason {}", statusCode, reason);
|
||||
this.session = null;
|
||||
// ensure execution stop if disconnect was triggered from server side
|
||||
interrupt();
|
||||
}
|
||||
|
||||
@OnWebSocketConnect
|
||||
public void onConnect(Session session) {
|
||||
accountHandler.updateStatus(ThingStatus.ONLINE);
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
@OnWebSocketError
|
||||
public void onError(Throwable t) {
|
||||
logger.warn("onError {}", t.getMessage());
|
||||
accountHandler.updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"@text/mercedesme.account.status.websocket-failure");
|
||||
}
|
||||
}
|
@ -1,92 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.mercedesme.internal.server;
|
||||
|
||||
import java.net.Inet4Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.SocketException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.mercedesme.internal.Constants;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link Utils} class defines an HTTP Server for authentication callbacks
|
||||
*
|
||||
* @author Bernd Weymann - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class Utils {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(Utils.class);
|
||||
private static final List<Integer> PORTS = new ArrayList<>();
|
||||
private static int port = 8090;
|
||||
|
||||
/**
|
||||
* Get free port without other Thread interference
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static synchronized int getFreePort() {
|
||||
while (PORTS.contains(port)) {
|
||||
port++;
|
||||
}
|
||||
PORTS.add(port);
|
||||
return port;
|
||||
}
|
||||
|
||||
public static synchronized void addPort(int portNr) {
|
||||
if (PORTS.contains(portNr)) {
|
||||
LOGGER.warn("Port {} already occupied", portNr);
|
||||
}
|
||||
PORTS.add(portNr);
|
||||
}
|
||||
|
||||
public static synchronized void removePort(int portNr) {
|
||||
PORTS.remove(Integer.valueOf(portNr));
|
||||
}
|
||||
|
||||
public static String getCallbackIP() throws SocketException {
|
||||
// https://stackoverflow.com/questions/901755/how-to-get-the-ip-of-the-computer-on-linux-through-java
|
||||
// https://stackoverflow.com/questions/1062041/ip-address-not-obtained-in-java
|
||||
for (Enumeration<NetworkInterface> ifaces = NetworkInterface.getNetworkInterfaces(); ifaces
|
||||
.hasMoreElements();) {
|
||||
NetworkInterface iface = ifaces.nextElement();
|
||||
try {
|
||||
if (!iface.isLoopback()) {
|
||||
if (iface.isUp()) {
|
||||
for (Enumeration<InetAddress> addresses = iface.getInetAddresses(); addresses
|
||||
.hasMoreElements();) {
|
||||
InetAddress address = addresses.nextElement();
|
||||
if (address instanceof Inet4Address) {
|
||||
return address.getHostAddress();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (SocketException se) {
|
||||
// Calling one network interface failed - continue searching
|
||||
LOGGER.trace("Network {} failed {}", iface.getName(), se.getMessage());
|
||||
}
|
||||
}
|
||||
throw new SocketException("IP address not detected");
|
||||
}
|
||||
|
||||
public static String getCallbackAddress(String callbackIP, int callbackPort) {
|
||||
return "http://" + callbackIP + Constants.COLON + callbackPort + Constants.CALLBACK_ENDPOINT;
|
||||
}
|
||||
}
|
@ -12,7 +12,10 @@
|
||||
*/
|
||||
package org.openhab.binding.mercedesme.internal.utils;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.types.State;
|
||||
|
||||
/**
|
||||
@ -25,13 +28,21 @@ public class ChannelStateMap {
|
||||
private String channel;
|
||||
private String group;
|
||||
private State state;
|
||||
private long timestamp;
|
||||
private Optional<UOMObserver> uomObserver = Optional.empty();
|
||||
|
||||
public ChannelStateMap(String ch, String grp, State st, long ts) {
|
||||
public ChannelStateMap(String ch, String grp, State st) {
|
||||
channel = ch;
|
||||
group = grp;
|
||||
state = st;
|
||||
timestamp = ts;
|
||||
}
|
||||
|
||||
public ChannelStateMap(String ch, String grp, State st, @Nullable UOMObserver uom) {
|
||||
channel = ch;
|
||||
group = grp;
|
||||
state = st;
|
||||
if (uom != null) {
|
||||
uomObserver = Optional.of(uom);
|
||||
}
|
||||
}
|
||||
|
||||
public String getChannel() {
|
||||
@ -46,13 +57,17 @@ public class ChannelStateMap {
|
||||
return state;
|
||||
}
|
||||
|
||||
public long getTimestamp() {
|
||||
return timestamp;
|
||||
public boolean hasUomObserver() {
|
||||
return !uomObserver.isEmpty();
|
||||
}
|
||||
|
||||
public UOMObserver getUomObserver() {
|
||||
return uomObserver.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return group + ":" + channel + " " + state;
|
||||
return group + "#" + channel + " " + state;
|
||||
}
|
||||
|
||||
public boolean isValid() {
|
||||
|
@ -14,24 +14,38 @@ package org.openhab.binding.mercedesme.internal.utils;
|
||||
|
||||
import static org.openhab.binding.mercedesme.internal.Constants.*;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.measure.Unit;
|
||||
import javax.measure.quantity.Length;
|
||||
import javax.measure.quantity.Pressure;
|
||||
import javax.measure.quantity.Speed;
|
||||
import javax.measure.quantity.Temperature;
|
||||
import javax.measure.quantity.Volume;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.json.JSONObject;
|
||||
import org.openhab.core.i18n.UnitProvider;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.library.types.OpenClosedType;
|
||||
import org.openhab.core.library.types.QuantityType;
|
||||
import org.openhab.core.library.types.StringType;
|
||||
import org.openhab.core.library.unit.ImperialUnits;
|
||||
import org.openhab.core.library.unit.SIUnits;
|
||||
import org.openhab.core.library.unit.Units;
|
||||
import org.openhab.core.types.State;
|
||||
import org.openhab.core.types.UnDefType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.daimler.mbcarkit.proto.VehicleEvents.VehicleAttributeStatus;
|
||||
|
||||
/**
|
||||
* The {@link Mapper} maps a given Json Object towards a channel, group and state
|
||||
* {@link Mapper} converts Mercedes keys to channel name and group and converts delivered vehicle data
|
||||
*
|
||||
* @author Bernd Weymann - Initial contribution
|
||||
*/
|
||||
@ -39,168 +53,291 @@ import org.slf4j.LoggerFactory;
|
||||
public class Mapper {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(Mapper.class);
|
||||
|
||||
public static final ChannelStateMap INVALID_MAP = new ChannelStateMap(EMPTY, EMPTY, UnDefType.UNDEF, -1);
|
||||
public static final ChannelStateMap INVALID_MAP = new ChannelStateMap(EMPTY, EMPTY, UnDefType.UNDEF);
|
||||
public static final Map<String, String[]> CHANNELS = new HashMap<>();
|
||||
public static final String TIMESTAMP = "timestamp";
|
||||
public static final String VALUE = "value";
|
||||
|
||||
public static ChannelStateMap getChannelStateMap(JSONObject jo) {
|
||||
public static Unit<Length> defaultLengthUnit = KILOMETRE_UNIT;
|
||||
public static Unit<Temperature> defaultTemperatureUnit = SIUnits.CELSIUS;
|
||||
public static Unit<Pressure> defaultPressureUnit = Units.BAR;
|
||||
public static Unit<Volume> defaultVolumeUnit = Units.LITRE;
|
||||
public static Unit<Speed> defaultSpeedUnit = SIUnits.KILOMETRE_PER_HOUR;
|
||||
|
||||
public static void initialize(UnitProvider up) {
|
||||
// Configure Mapper default values
|
||||
Unit<Length> lengthUnit = up.getUnit(Length.class);
|
||||
if (ImperialUnits.FOOT.equals(lengthUnit)) {
|
||||
defaultLengthUnit = ImperialUnits.MILE;
|
||||
defaultSpeedUnit = ImperialUnits.MILES_PER_HOUR;
|
||||
defaultPressureUnit = ImperialUnits.POUND_FORCE_SQUARE_INCH;
|
||||
defaultVolumeUnit = ImperialUnits.GALLON_LIQUID_US;
|
||||
}
|
||||
Unit<Temperature> temperatureUnit = up.getUnit(Temperature.class);
|
||||
defaultTemperatureUnit = temperatureUnit;
|
||||
}
|
||||
|
||||
public static ChannelStateMap getChannelStateMap(String key, VehicleAttributeStatus value) {
|
||||
if (CHANNELS.isEmpty()) {
|
||||
init();
|
||||
}
|
||||
Set<String> s = jo.keySet();
|
||||
if (s.size() == 1) {
|
||||
String id = s.toArray()[0].toString();
|
||||
String[] ch = CHANNELS.get(id);
|
||||
if (ch != null) {
|
||||
State state;
|
||||
switch (id) {
|
||||
// Kilometer values
|
||||
case "odo":
|
||||
case "rangeelectric":
|
||||
case "rangeliquid":
|
||||
state = getKilometers((JSONObject) jo.get(id));
|
||||
return new ChannelStateMap(ch[0], ch[1], state, getTimestamp((JSONObject) jo.get(id)));
|
||||
String[] ch = CHANNELS.get(key);
|
||||
if (ch != null) {
|
||||
State state;
|
||||
UOMObserver observer = null;
|
||||
switch (key) {
|
||||
// Kilometer values
|
||||
case MB_KEY_ODO:
|
||||
case MB_KEY_RANGEELECTRIC:
|
||||
case MB_KEY_OVERALL_RANGE:
|
||||
case MB_KEY_RANGELIQUID:
|
||||
case MB_KEY_DISTANCE_START:
|
||||
case MB_KEY_DISTANCE_RESET:
|
||||
Unit<?> lengthUnit = defaultLengthUnit;
|
||||
if (value.hasDistanceUnit()) {
|
||||
observer = new UOMObserver(value.getDistanceUnit().toString());
|
||||
Unit<?> queryUnit = observer.getUnit();
|
||||
if (queryUnit != null) {
|
||||
lengthUnit = queryUnit;
|
||||
} else {
|
||||
LOGGER.trace("No Unit found for {} - take default ", key);
|
||||
}
|
||||
}
|
||||
state = QuantityType.valueOf(Utils.getDouble(value), lengthUnit);
|
||||
return new ChannelStateMap(ch[0], ch[1], state, observer);
|
||||
|
||||
// Percentages
|
||||
case "soc":
|
||||
case "tanklevelpercent":
|
||||
state = getPercentage((JSONObject) jo.get(id));
|
||||
return new ChannelStateMap(ch[0], ch[1], state, getTimestamp((JSONObject) jo.get(id)));
|
||||
// special String Value
|
||||
case MB_KEY_DRIVEN_TIME_START:
|
||||
case MB_KEY_DRIVEN_TIME_RESET:
|
||||
int duration = Utils.getInt(value);
|
||||
if (duration < 0) {
|
||||
state = UnDefType.UNDEF;
|
||||
} else {
|
||||
state = StringType.valueOf(Utils.getDurationString(duration));
|
||||
}
|
||||
return new ChannelStateMap(ch[0], ch[1], state);
|
||||
|
||||
// Contacts
|
||||
case "decklidstatus":
|
||||
case "doorstatusfrontleft":
|
||||
case "doorstatusfrontright":
|
||||
case "doorstatusrearleft":
|
||||
case "doorstatusrearright":
|
||||
state = getContact((JSONObject) jo.get(id));
|
||||
return new ChannelStateMap(ch[0], ch[1], state, getTimestamp((JSONObject) jo.get(id)));
|
||||
// KiloWatt values
|
||||
case MB_KEY_CHARGING_POWER:
|
||||
double power = Utils.getDouble(value);
|
||||
state = QuantityType.valueOf(Math.max(0, power), KILOWATT_UNIT);
|
||||
return new ChannelStateMap(ch[0], ch[1], state);
|
||||
|
||||
// Number Status
|
||||
case "lightswitchposition":
|
||||
case "rooftopstatus":
|
||||
case "sunroofstatus":
|
||||
case "windowstatusfrontleft":
|
||||
case "windowstatusfrontright":
|
||||
case "windowstatusrearleft":
|
||||
case "windowstatusrearright":
|
||||
case "doorlockstatusvehicle":
|
||||
state = getDecimal((JSONObject) jo.get(id));
|
||||
return new ChannelStateMap(ch[0], ch[1], state, getTimestamp((JSONObject) jo.get(id)));
|
||||
case MB_KEY_AVERAGE_SPEED_START:
|
||||
case MB_KEY_AVERAGE_SPEED_RESET:
|
||||
Unit<?> speedUnit = defaultSpeedUnit;
|
||||
if (value.hasSpeedUnit()) {
|
||||
observer = new UOMObserver(value.getSpeedUnit().toString());
|
||||
Unit<?> queryUnit = observer.getUnit();
|
||||
if (queryUnit != null) {
|
||||
lengthUnit = observer.getUnit();
|
||||
} else {
|
||||
LOGGER.trace("No Unit found for {} - take default ", key);
|
||||
}
|
||||
}
|
||||
double speed = Utils.getDouble(value);
|
||||
state = QuantityType.valueOf(Math.max(0, speed), speedUnit);
|
||||
return new ChannelStateMap(ch[0], ch[1], state, observer);
|
||||
|
||||
// Switches
|
||||
case "interiorLightsFront":
|
||||
case "interiorLightsRear":
|
||||
case "readingLampFrontLeft":
|
||||
case "readingLampFrontRight":
|
||||
state = getOnOffType((JSONObject) jo.get(id));
|
||||
return new ChannelStateMap(ch[0], ch[1], state, getTimestamp((JSONObject) jo.get(id)));
|
||||
// KiloWatt/Hour values
|
||||
case MB_KEY_ELECTRICCONSUMPTIONSTART:
|
||||
case MB_KEY_ELECTRICCONSUMPTIONRESET:
|
||||
double consumptionEv = Utils.getDouble(value);
|
||||
state = new DecimalType(consumptionEv);
|
||||
if (value.hasElectricityConsumptionUnit()) {
|
||||
observer = new UOMObserver(value.getElectricityConsumptionUnit().toString());
|
||||
} else {
|
||||
LOGGER.trace("Don't have electric consumption unit for {}", key);
|
||||
}
|
||||
return new ChannelStateMap(ch[0], ch[1], state, observer);
|
||||
|
||||
case "doorlockstatusdecklid":
|
||||
case "doorlockstatusgas":
|
||||
state = getOnOffTypeLock((JSONObject) jo.get(id));
|
||||
return new ChannelStateMap(ch[0], ch[1], state, getTimestamp((JSONObject) jo.get(id)));
|
||||
// Litre values
|
||||
case MB_KEY_LIQUIDCONSUMPTIONSTART:
|
||||
case MB_KEY_LIQUIDCONSUMPTIONRESET:
|
||||
double consumptionComb = Utils.getDouble(value);
|
||||
state = new DecimalType(consumptionComb);
|
||||
if (value.hasCombustionConsumptionUnit()) {
|
||||
observer = new UOMObserver(value.getCombustionConsumptionUnit().toString());
|
||||
}
|
||||
return new ChannelStateMap(ch[0], ch[1], state, observer);
|
||||
|
||||
// Angle
|
||||
case "positionHeading":
|
||||
state = getAngle((JSONObject) jo.get(id));
|
||||
return new ChannelStateMap(ch[0], ch[1], state, getTimestamp((JSONObject) jo.get(id)));
|
||||
default:
|
||||
LOGGER.trace("No mapping available for {}", id);
|
||||
}
|
||||
} else {
|
||||
LOGGER.trace("No mapping available for {}", id);
|
||||
// Time - end of charging
|
||||
case MB_KEY_ENDOFCHARGETIME:
|
||||
if (Utils.isNil(value)) {
|
||||
state = UnDefType.UNDEF;
|
||||
} else {
|
||||
// int value is representing "minutes after Midnight!
|
||||
Instant time = Instant.ofEpochMilli(value.getTimestampInMs());
|
||||
long minutesAddon = Utils.getInt(value);
|
||||
time.plus(minutesAddon, ChronoUnit.MINUTES);
|
||||
state = Utils.getEndOfChargeTime(time.toEpochMilli(), minutesAddon);
|
||||
if (Locale.US.getCountry().equals(Utils.getCountry())) {
|
||||
observer = new UOMObserver(UOMObserver.TIME_US);
|
||||
} else {
|
||||
observer = new UOMObserver(UOMObserver.TIME_ROW);
|
||||
}
|
||||
}
|
||||
return new ChannelStateMap(ch[0], ch[1], state, observer);
|
||||
|
||||
// DateTime - last Update
|
||||
case MB_KEY_TIRE_PRESS_MEAS_TIMESTAMP:
|
||||
if (Utils.isNil(value)) {
|
||||
state = UnDefType.UNDEF;
|
||||
} else {
|
||||
state = Utils.getDateTimeType(value.getTimestampInMs());
|
||||
}
|
||||
if (Locale.US.getCountry().equals(Utils.getCountry())) {
|
||||
observer = new UOMObserver(UOMObserver.TIME_US);
|
||||
} else {
|
||||
observer = new UOMObserver(UOMObserver.TIME_ROW);
|
||||
}
|
||||
return new ChannelStateMap(ch[0], ch[1], state, observer);
|
||||
|
||||
// Percentages
|
||||
case MB_KEY_SOC:
|
||||
case MB_KEY_TANKLEVELPERCENT:
|
||||
double level = Utils.getDouble(value);
|
||||
state = QuantityType.valueOf(level, Units.PERCENT);
|
||||
return new ChannelStateMap(ch[0], ch[1], state);
|
||||
|
||||
// Contacts
|
||||
case MB_KEY_DOORSTATUSFRONTRIGHT:
|
||||
case MB_KEY_DOORSTATUSFRONTLEFT:
|
||||
case MB_KEY_DOORSTATUSREARRIGHT:
|
||||
case MB_KEY_DOORSTATUSREARLEFT:
|
||||
case MB_KEY_DECKLIDSTATUS:
|
||||
case MB_KEY_ENGINE_HOOD_STATUS:
|
||||
if (Utils.isNil(value)) {
|
||||
state = UnDefType.UNDEF;
|
||||
} else {
|
||||
state = getContact(value.getBoolValue());
|
||||
}
|
||||
return new ChannelStateMap(ch[0], ch[1], state);
|
||||
|
||||
// Number Status
|
||||
case MB_KEY_DOOR_LOCK_STATUS_OVERALL:
|
||||
case MB_KEY_WINDOW_STATUS_OVERALL:
|
||||
case MB_KEY_DOOR_STATUS_OVERALL:
|
||||
case MB_KEY_IGNITIONSTATE:
|
||||
case MB_KEY_SUNROOFSTATUS:
|
||||
case MB_KEY_SUNROOF_STATUS_FRONT_BLIND:
|
||||
case MB_KEY_SUNROOF_STATUS_REAR_BLIND:
|
||||
case MB_KEY_ROOFTOPSTATUS:
|
||||
case MB_KEY_WINDOWSTATUSFRONTLEFT:
|
||||
case MB_KEY_WINDOWSTATUSFRONTRIGHT:
|
||||
case MB_KEY_WINDOWSTATUSREARLEFT:
|
||||
case MB_KEY_WINDOWSTATUSREARRIGHT:
|
||||
case MB_KEY_WINDOW_STATUS_REAR_RIGHT_BLIND:
|
||||
case MB_KEY_WINDOW_STATUS_REAR_LEFT_BLIND:
|
||||
case MB_KEY_WINDOW_STATUS_REAR_BLIND:
|
||||
case MB_KEY_FLIP_WINDOW_STATUS:
|
||||
case MB_KEY_STARTER_BATTERY_STATE:
|
||||
case MB_KEY_TIREWARNINGSRDK:
|
||||
case MB_KEY_SERVICEINTERVALDAYS:
|
||||
case MB_KEY_CHARGE_FLAP_DC_STATUS:
|
||||
case MB_KEY_CHARGE_COUPLER_AC_STATUS:
|
||||
case MB_KEY_CHARGE_COUPLER_DC_STATUS:
|
||||
case MB_KEY_CHARGE_COUPLER_DC_LOCK_STATUS:
|
||||
case MB_KEY_TIRE_SENSOR_AVAILABLE:
|
||||
int stateNumberInteger = Utils.getInt(value);
|
||||
if (stateNumberInteger < 0) {
|
||||
state = UnDefType.UNDEF;
|
||||
} else {
|
||||
state = new DecimalType(stateNumberInteger);
|
||||
}
|
||||
return new ChannelStateMap(ch[0], ch[1], state);
|
||||
|
||||
case MB_KEY_TIRE_MARKER_FRONT_RIGHT:
|
||||
case MB_KEY_TIRE_MARKER_FRONT_LEFT:
|
||||
case MB_KEY_TIRE_MARKER_REAR_RIGHT:
|
||||
case MB_KEY_TIRE_MARKER_REAR_LEFT:
|
||||
double stateNumberDouble = Utils.getDouble(value);
|
||||
if (stateNumberDouble < 0) {
|
||||
state = UnDefType.UNDEF;
|
||||
} else {
|
||||
state = new DecimalType(stateNumberDouble);
|
||||
}
|
||||
return new ChannelStateMap(ch[0], ch[1], state);
|
||||
|
||||
// Switches
|
||||
case MB_KEY_PARKBRAKESTATUS:
|
||||
case MB_KEY_PRECOND_NOW:
|
||||
case MB_KEY_PRECOND_SEAT_FRONT_RIGHT:
|
||||
case MB_KEY_PRECOND_SEAT_FRONT_LEFT:
|
||||
case MB_KEY_PRECOND_SEAT_REAR_RIGHT:
|
||||
case MB_KEY_PRECOND_SEAT_REAR_LEFT:
|
||||
case MB_KEY_WARNINGBRAKEFLUID:
|
||||
case MB_KEY_WARNINGBRAKELININGWEAR:
|
||||
case MB_KEY_WARNINGWASHWATER:
|
||||
case MB_KEY_WARNINGCOOLANTLEVELLOW:
|
||||
case MB_KEY_WARNINGENGINELIGHT:
|
||||
case MB_KEY_CHARGINGACTIVE:
|
||||
if (Utils.isNil(value)) {
|
||||
state = UnDefType.UNDEF;
|
||||
} else {
|
||||
if (value.hasBoolValue()) {
|
||||
state = OnOffType.from(value.getBoolValue());
|
||||
} else {
|
||||
state = UnDefType.UNDEF;
|
||||
}
|
||||
}
|
||||
return new ChannelStateMap(ch[0], ch[1], state);
|
||||
|
||||
// Switches - lock values with reversed boolean interpretation
|
||||
case MB_KEY_DOORLOCKSTATUSFRONTRIGHT:
|
||||
case MB_KEY_DOORLOCKSTATUSFRONTLEFT:
|
||||
case MB_KEY_DOORLOCKSTATUSREARRIGHT:
|
||||
case MB_KEY_DOORLOCKSTATUSREARLEFT:
|
||||
case MB_KEY_DOORLOCKSTATUSDECKLID:
|
||||
case MB_KEY_DOORLOCKSTATUSGAS:
|
||||
if (Utils.isNil(value)) {
|
||||
state = UnDefType.UNDEF;
|
||||
} else {
|
||||
// sad but true - false means locked
|
||||
state = OnOffType.from(!value.getBoolValue());
|
||||
}
|
||||
return new ChannelStateMap(ch[0], ch[1], state);
|
||||
|
||||
// Angle
|
||||
case MB_KEY_POSITION_HEADING:
|
||||
double heading = Utils.getDouble(value);
|
||||
if (heading < 0) {
|
||||
state = UnDefType.UNDEF;
|
||||
} else {
|
||||
state = QuantityType.valueOf(heading, Units.DEGREE_ANGLE);
|
||||
}
|
||||
return new ChannelStateMap(ch[0], ch[1], state);
|
||||
|
||||
// tires
|
||||
case MB_KEY_TIREPRESSURE_FRONT_LEFT:
|
||||
case MB_KEY_TIREPRESSURE_FRONT_RIGHT:
|
||||
case MB_KEY_TIREPRESSURE_REAR_LEFT:
|
||||
case MB_KEY_TIREPRESSURE_REAR_RIGHT:
|
||||
Unit<?> pressureUnit = defaultPressureUnit;
|
||||
if (value.hasPressureUnit()) {
|
||||
observer = new UOMObserver(value.getPressureUnit().toString());
|
||||
Unit<?> queryUnit = observer.getUnit();
|
||||
if (queryUnit != null) {
|
||||
pressureUnit = queryUnit;
|
||||
} else {
|
||||
LOGGER.trace("No Unit found for {} - take default ", key);
|
||||
}
|
||||
}
|
||||
double pressure = Utils.getDouble(value);
|
||||
state = QuantityType.valueOf(pressure, pressureUnit);
|
||||
return new ChannelStateMap(ch[0], ch[1], state, observer);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
LOGGER.debug("More than one key found {}", s);
|
||||
}
|
||||
return INVALID_MAP;
|
||||
}
|
||||
|
||||
private static long getTimestamp(JSONObject jo) {
|
||||
if (jo.has(TIMESTAMP)) {
|
||||
return jo.getLong(TIMESTAMP);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private static State getOnOffType(JSONObject jo) {
|
||||
if (jo.has(VALUE)) {
|
||||
String value = jo.get(VALUE).toString();
|
||||
boolean b = Boolean.valueOf(value);
|
||||
return OnOffType.from(b);
|
||||
private static State getContact(boolean b) {
|
||||
if (!b) {
|
||||
return OpenClosedType.CLOSED;
|
||||
} else {
|
||||
LOGGER.warn("JSONObject contains no value {}", jo);
|
||||
return UnDefType.UNDEF;
|
||||
}
|
||||
}
|
||||
|
||||
private static State getOnOffTypeLock(JSONObject jo) {
|
||||
if (jo.has(VALUE)) {
|
||||
String value = jo.get(VALUE).toString();
|
||||
boolean b = Boolean.valueOf(value);
|
||||
// Yes, false is locked and true unlocked
|
||||
// https://developer.mercedes-benz.com/products/vehicle_lock_status/specifications/vehicle_lock_status_api
|
||||
return OnOffType.from(!b);
|
||||
} else {
|
||||
LOGGER.warn("JSONObject contains no value {}", jo);
|
||||
return UnDefType.UNDEF;
|
||||
}
|
||||
}
|
||||
|
||||
private static State getAngle(JSONObject jo) {
|
||||
if (jo.has(VALUE)) {
|
||||
String value = jo.get(VALUE).toString();
|
||||
return QuantityType.valueOf(Double.valueOf(value), Units.DEGREE_ANGLE);
|
||||
} else {
|
||||
LOGGER.warn("JSONObject contains no value {}", jo);
|
||||
return UnDefType.UNDEF;
|
||||
}
|
||||
}
|
||||
|
||||
private static State getDecimal(JSONObject jo) {
|
||||
if (jo.has(VALUE)) {
|
||||
String value = jo.get(VALUE).toString();
|
||||
return DecimalType.valueOf(value);
|
||||
} else {
|
||||
LOGGER.warn("JSONObject contains no value {}", jo);
|
||||
return UnDefType.UNDEF;
|
||||
}
|
||||
}
|
||||
|
||||
private static State getContact(JSONObject jo) {
|
||||
if (jo.has(VALUE)) {
|
||||
String value = jo.get(VALUE).toString();
|
||||
boolean b = Boolean.valueOf(value);
|
||||
if (!b) {
|
||||
return OpenClosedType.CLOSED;
|
||||
} else {
|
||||
return OpenClosedType.OPEN;
|
||||
}
|
||||
} else {
|
||||
LOGGER.warn("JSONObject contains no value {}", jo);
|
||||
return UnDefType.UNDEF;
|
||||
}
|
||||
}
|
||||
|
||||
private static State getKilometers(JSONObject jo) {
|
||||
if (jo.has(VALUE)) {
|
||||
String value = jo.get(VALUE).toString();
|
||||
return QuantityType.valueOf(Integer.valueOf(value), KILOMETRE_UNIT);
|
||||
} else {
|
||||
LOGGER.warn("JSONObject contains no value {}", jo);
|
||||
return UnDefType.UNDEF;
|
||||
}
|
||||
}
|
||||
|
||||
private static State getPercentage(JSONObject jo) {
|
||||
if (jo.has(VALUE)) {
|
||||
String value = jo.get(VALUE).toString();
|
||||
return QuantityType.valueOf(Integer.valueOf(value), Units.PERCENT);
|
||||
} else {
|
||||
LOGGER.warn("JSONObject contains no value {}", jo);
|
||||
return UnDefType.UNDEF;
|
||||
return OpenClosedType.OPEN;
|
||||
}
|
||||
}
|
||||
|
||||
@ -208,30 +345,93 @@ public class Mapper {
|
||||
* Mapping of json id towards channel group and id
|
||||
*/
|
||||
private static void init() {
|
||||
CHANNELS.put("odo", new String[] { "mileage", GROUP_RANGE });
|
||||
CHANNELS.put("rangeelectric", new String[] { "range-electric", GROUP_RANGE });
|
||||
CHANNELS.put("soc", new String[] { "soc", GROUP_RANGE });
|
||||
CHANNELS.put("rangeliquid", new String[] { "range-fuel", GROUP_RANGE });
|
||||
CHANNELS.put("tanklevelpercent", new String[] { "fuel-level", GROUP_RANGE });
|
||||
CHANNELS.put("decklidstatus", new String[] { "deck-lid", GROUP_DOORS });
|
||||
CHANNELS.put("doorstatusfrontleft", new String[] { "driver-front", GROUP_DOORS });
|
||||
CHANNELS.put("doorstatusfrontright", new String[] { "passenger-front", GROUP_DOORS });
|
||||
CHANNELS.put("doorstatusrearleft", new String[] { "driver-rear", GROUP_DOORS });
|
||||
CHANNELS.put("doorstatusrearright", new String[] { "passenger-rear", GROUP_DOORS });
|
||||
CHANNELS.put("interiorLightsFront", new String[] { "interior-front", GROUP_LIGHTS });
|
||||
CHANNELS.put("interiorLightsRear", new String[] { "interior-rear", GROUP_LIGHTS });
|
||||
CHANNELS.put("lightswitchposition", new String[] { "light-switch", GROUP_LIGHTS });
|
||||
CHANNELS.put("readingLampFrontLeft", new String[] { "reading-left", GROUP_LIGHTS });
|
||||
CHANNELS.put("readingLampFrontRight", new String[] { "reading-right", GROUP_LIGHTS });
|
||||
CHANNELS.put("rooftopstatus", new String[] { "rooftop", GROUP_DOORS });
|
||||
CHANNELS.put("sunroofstatus", new String[] { "sunroof", GROUP_DOORS });
|
||||
CHANNELS.put("windowstatusfrontleft", new String[] { "driver-front", GROUP_WINDOWS });
|
||||
CHANNELS.put("windowstatusfrontright", new String[] { "passenger-front", GROUP_WINDOWS });
|
||||
CHANNELS.put("windowstatusrearleft", new String[] { "driver-rear", GROUP_WINDOWS });
|
||||
CHANNELS.put("windowstatusrearright", new String[] { "passenger-rear", GROUP_WINDOWS });
|
||||
CHANNELS.put("doorlockstatusvehicle", new String[] { "doors", GROUP_LOCK });
|
||||
CHANNELS.put("doorlockstatusdecklid", new String[] { "deck-lid", GROUP_LOCK });
|
||||
CHANNELS.put("doorlockstatusgas", new String[] { "flap", GROUP_LOCK });
|
||||
CHANNELS.put("positionHeading", new String[] { "heading", GROUP_LOCATION });
|
||||
CHANNELS.put(MB_KEY_DOOR_LOCK_STATUS_OVERALL, new String[] { OH_CHANNEL_LOCK, GROUP_VEHICLE });
|
||||
CHANNELS.put(MB_KEY_WINDOW_STATUS_OVERALL, new String[] { OH_CHANNEL_WINDOWS, GROUP_VEHICLE });
|
||||
CHANNELS.put(MB_KEY_DOOR_STATUS_OVERALL, new String[] { OH_CHANNEL_DOOR_STATUS, GROUP_VEHICLE });
|
||||
CHANNELS.put(MB_KEY_IGNITIONSTATE, new String[] { OH_CHANNEL_IGNITION, GROUP_VEHICLE });
|
||||
CHANNELS.put(MB_KEY_PARKBRAKESTATUS, new String[] { OH_CHANNEL_PARK_BRAKE, GROUP_VEHICLE });
|
||||
|
||||
CHANNELS.put(MB_KEY_DOORSTATUSFRONTRIGHT, new String[] { OH_CHANNEL_FRONT_RIGHT, GROUP_DOORS });
|
||||
CHANNELS.put(MB_KEY_DOORSTATUSFRONTLEFT, new String[] { OH_CHANNEL_FRONT_LEFT, GROUP_DOORS });
|
||||
CHANNELS.put(MB_KEY_DOORSTATUSREARRIGHT, new String[] { OH_CHANNEL_REAR_RIGHT, GROUP_DOORS });
|
||||
CHANNELS.put(MB_KEY_DOORSTATUSREARLEFT, new String[] { OH_CHANNEL_REAR_LEFT, GROUP_DOORS });
|
||||
CHANNELS.put(MB_KEY_DECKLIDSTATUS, new String[] { OH_CHANNEL_DECK_LID, GROUP_DOORS });
|
||||
CHANNELS.put(MB_KEY_ENGINE_HOOD_STATUS, new String[] { OH_CHANNEL_ENGINE_HOOD, GROUP_DOORS });
|
||||
CHANNELS.put(MB_KEY_SUNROOFSTATUS, new String[] { OH_CHANNEL_SUNROOF, GROUP_DOORS });
|
||||
CHANNELS.put(MB_KEY_SUNROOF_STATUS_FRONT_BLIND, new String[] { OH_CHANNEL_SUNROOF_FRONT_BLIND, GROUP_DOORS });
|
||||
CHANNELS.put(MB_KEY_SUNROOF_STATUS_REAR_BLIND, new String[] { OH_CHANNEL_SUNROOF_REAR_BLIND, GROUP_DOORS });
|
||||
CHANNELS.put(MB_KEY_ROOFTOPSTATUS, new String[] { OH_CHANNEL_ROOFTOP, GROUP_DOORS });
|
||||
|
||||
CHANNELS.put(MB_KEY_DOORLOCKSTATUSFRONTRIGHT, new String[] { OH_CHANNEL_FRONT_RIGHT, GROUP_LOCK });
|
||||
CHANNELS.put(MB_KEY_DOORLOCKSTATUSFRONTLEFT, new String[] { OH_CHANNEL_FRONT_LEFT, GROUP_LOCK });
|
||||
CHANNELS.put(MB_KEY_DOORLOCKSTATUSREARRIGHT, new String[] { OH_CHANNEL_REAR_RIGHT, GROUP_LOCK });
|
||||
CHANNELS.put(MB_KEY_DOORLOCKSTATUSREARLEFT, new String[] { OH_CHANNEL_REAR_LEFT, GROUP_LOCK });
|
||||
CHANNELS.put(MB_KEY_DOORLOCKSTATUSDECKLID, new String[] { OH_CHANNEL_DECK_LID, GROUP_LOCK });
|
||||
CHANNELS.put(MB_KEY_DOORLOCKSTATUSGAS, new String[] { OH_CHANNEL_GAS_FLAP, GROUP_LOCK });
|
||||
|
||||
CHANNELS.put(MB_KEY_WINDOWSTATUSFRONTLEFT, new String[] { OH_CHANNEL_FRONT_LEFT, GROUP_WINDOWS });
|
||||
CHANNELS.put(MB_KEY_WINDOWSTATUSFRONTRIGHT, new String[] { OH_CHANNEL_FRONT_RIGHT, GROUP_WINDOWS });
|
||||
CHANNELS.put(MB_KEY_WINDOWSTATUSREARLEFT, new String[] { OH_CHANNEL_REAR_LEFT, GROUP_WINDOWS });
|
||||
CHANNELS.put(MB_KEY_WINDOWSTATUSREARRIGHT, new String[] { OH_CHANNEL_REAR_RIGHT, GROUP_WINDOWS });
|
||||
CHANNELS.put(MB_KEY_WINDOW_STATUS_REAR_RIGHT_BLIND,
|
||||
new String[] { OH_CHANNEL_REAR_RIGHT_BLIND, GROUP_WINDOWS });
|
||||
CHANNELS.put(MB_KEY_WINDOW_STATUS_REAR_LEFT_BLIND, new String[] { OH_CHANNEL_REAR_LEFT_BLIND, GROUP_WINDOWS });
|
||||
CHANNELS.put(MB_KEY_WINDOW_STATUS_REAR_BLIND, new String[] { OH_CHANNEL_REAR_BLIND, GROUP_WINDOWS });
|
||||
CHANNELS.put(MB_KEY_FLIP_WINDOW_STATUS, new String[] { OH_CHANNEL_FLIP_WINDOW, GROUP_WINDOWS });
|
||||
|
||||
CHANNELS.put(MB_KEY_PRECOND_NOW, new String[] { OH_CHANNEL_ACTIVE, GROUP_HVAC });
|
||||
CHANNELS.put(MB_KEY_PRECOND_SEAT_FRONT_RIGHT, new String[] { OH_CHANNEL_FRONT_RIGHT, GROUP_HVAC });
|
||||
CHANNELS.put(MB_KEY_PRECOND_SEAT_FRONT_LEFT, new String[] { OH_CHANNEL_FRONT_LEFT, GROUP_HVAC });
|
||||
CHANNELS.put(MB_KEY_PRECOND_SEAT_REAR_RIGHT, new String[] { OH_CHANNEL_REAR_RIGHT, GROUP_HVAC });
|
||||
CHANNELS.put(MB_KEY_PRECOND_SEAT_REAR_LEFT, new String[] { OH_CHANNEL_REAR_LEFT, GROUP_HVAC });
|
||||
// temperaturePoints - special handling: sets zone & temperature
|
||||
|
||||
CHANNELS.put(MB_KEY_STARTER_BATTERY_STATE, new String[] { OH_CHANNEL_STARTER_BATTERY, GROUP_SERVICE });
|
||||
CHANNELS.put(MB_KEY_WARNINGBRAKEFLUID, new String[] { OH_CHANNEL_BRAKE_FLUID, GROUP_SERVICE });
|
||||
CHANNELS.put(MB_KEY_WARNINGWASHWATER, new String[] { OH_CHANNEL_WASH_WATER, GROUP_SERVICE });
|
||||
CHANNELS.put(MB_KEY_WARNINGBRAKELININGWEAR, new String[] { OH_CHANNEL_BRAKE_LINING_WEAR, GROUP_SERVICE });
|
||||
CHANNELS.put(MB_KEY_WARNINGCOOLANTLEVELLOW, new String[] { OH_CHANNEL_COOLANT_FLUID, GROUP_SERVICE });
|
||||
CHANNELS.put(MB_KEY_WARNINGENGINELIGHT, new String[] { OH_CHANNEL_ENGINE, GROUP_SERVICE });
|
||||
CHANNELS.put(MB_KEY_TIREWARNINGSRDK, new String[] { OH_CHANNEL_TIRES_RDK, GROUP_SERVICE });
|
||||
CHANNELS.put(MB_KEY_SERVICEINTERVALDAYS, new String[] { OH_CHANNEL_SERVICE_DAYS, GROUP_SERVICE });
|
||||
|
||||
CHANNELS.put(MB_KEY_ODO, new String[] { OH_CHANNEL_MILEAGE, GROUP_RANGE });
|
||||
CHANNELS.put(MB_KEY_RANGEELECTRIC, new String[] { OH_CHANNEL_RANGE_ELECTRIC, GROUP_RANGE });
|
||||
CHANNELS.put(MB_KEY_SOC, new String[] { MB_KEY_SOC, GROUP_RANGE });
|
||||
CHANNELS.put(MB_KEY_RANGELIQUID, new String[] { OH_CHANNEL_RANGE_FUEL, GROUP_RANGE });
|
||||
CHANNELS.put(MB_KEY_OVERALL_RANGE, new String[] { OH_CHANNEL_RANGE_HYBRID, GROUP_RANGE });
|
||||
CHANNELS.put(MB_KEY_TANKLEVELPERCENT, new String[] { OH_CHANNEL_FUEL_LEVEL, GROUP_RANGE });
|
||||
|
||||
CHANNELS.put(MB_KEY_CHARGE_FLAP_DC_STATUS, new String[] { OH_CHANNEL_CHARGE_FLAP, GROUP_CHARGE });
|
||||
CHANNELS.put(MB_KEY_CHARGE_COUPLER_AC_STATUS, new String[] { OH_CHANNEL_COUPLER_AC, GROUP_CHARGE });
|
||||
CHANNELS.put(MB_KEY_CHARGE_COUPLER_DC_STATUS, new String[] { OH_CHANNEL_COUPLER_DC, GROUP_CHARGE });
|
||||
CHANNELS.put(MB_KEY_CHARGE_COUPLER_DC_LOCK_STATUS, new String[] { OH_CHANNEL_COUPLER_LOCK, GROUP_CHARGE });
|
||||
CHANNELS.put(MB_KEY_CHARGINGACTIVE, new String[] { OH_CHANNEL_ACTIVE, GROUP_CHARGE });
|
||||
CHANNELS.put(MB_KEY_CHARGING_POWER, new String[] { OH_CHANNEL_POWER, GROUP_CHARGE });
|
||||
CHANNELS.put(MB_KEY_ENDOFCHARGETIME, new String[] { OH_CHANNEL_END_TIME, GROUP_CHARGE });
|
||||
|
||||
CHANNELS.put(MB_KEY_POSITION_HEADING, new String[] { OH_CHANNEL_HEADING, GROUP_POSITION });
|
||||
|
||||
CHANNELS.put(MB_KEY_DISTANCE_START, new String[] { OH_CHANNEL_DISTANCE, GROUP_TRIP });
|
||||
CHANNELS.put(MB_KEY_DRIVEN_TIME_START, new String[] { OH_CHANNEL_TIME, GROUP_TRIP });
|
||||
CHANNELS.put(MB_KEY_AVERAGE_SPEED_START, new String[] { OH_CHANNEL_AVG_SPEED, GROUP_TRIP });
|
||||
CHANNELS.put(MB_KEY_ELECTRICCONSUMPTIONSTART, new String[] { OH_CHANNEL_CONS_EV, GROUP_TRIP });
|
||||
CHANNELS.put(MB_KEY_LIQUIDCONSUMPTIONSTART, new String[] { OH_CHANNEL_CONS_CONV, GROUP_TRIP });
|
||||
CHANNELS.put(MB_KEY_DISTANCE_RESET, new String[] { OH_CHANNEL_DISTANCE_RESET, GROUP_TRIP });
|
||||
CHANNELS.put(MB_KEY_DRIVEN_TIME_RESET, new String[] { OH_CHANNEL_TIME_RESET, GROUP_TRIP });
|
||||
CHANNELS.put(MB_KEY_AVERAGE_SPEED_RESET, new String[] { OH_CHANNEL_AVG_SPEED_RESET, GROUP_TRIP });
|
||||
CHANNELS.put(MB_KEY_ELECTRICCONSUMPTIONRESET, new String[] { OH_CHANNEL_CONS_EV_RESET, GROUP_TRIP });
|
||||
CHANNELS.put(MB_KEY_LIQUIDCONSUMPTIONRESET, new String[] { OH_CHANNEL_CONS_CONV_RESET, GROUP_TRIP });
|
||||
|
||||
CHANNELS.put(MB_KEY_TIREPRESSURE_REAR_RIGHT, new String[] { OH_CHANNEL_PRESSURE_REAR_RIGHT, GROUP_TIRES });
|
||||
CHANNELS.put(MB_KEY_TIREPRESSURE_FRONT_RIGHT, new String[] { OH_CHANNEL_PRESSURE_FRONT_RIGHT, GROUP_TIRES });
|
||||
CHANNELS.put(MB_KEY_TIREPRESSURE_REAR_LEFT, new String[] { OH_CHANNEL_PRESSURE_REAR_LEFT, GROUP_TIRES });
|
||||
CHANNELS.put(MB_KEY_TIREPRESSURE_FRONT_LEFT, new String[] { OH_CHANNEL_PRESSURE_FRONT_LEFT, GROUP_TIRES });
|
||||
CHANNELS.put(MB_KEY_TIRE_MARKER_FRONT_RIGHT, new String[] { OH_CHANNEL_MARKER_REAR_RIGHT, GROUP_TIRES });
|
||||
CHANNELS.put(MB_KEY_TIRE_MARKER_FRONT_LEFT, new String[] { OH_CHANNEL_MARKER_FRONT_RIGHT, GROUP_TIRES });
|
||||
CHANNELS.put(MB_KEY_TIRE_MARKER_REAR_RIGHT, new String[] { OH_CHANNEL_MARKER_REAR_LEFT, GROUP_TIRES });
|
||||
CHANNELS.put(MB_KEY_TIRE_MARKER_REAR_LEFT, new String[] { OH_CHANNEL_MARKER_FRONT_LEFT, GROUP_TIRES });
|
||||
CHANNELS.put(MB_KEY_TIRE_SENSOR_AVAILABLE, new String[] { OH_CHANNEL_SENSOR_AVAILABLE, GROUP_TIRES });
|
||||
CHANNELS.put(MB_KEY_TIRE_PRESS_MEAS_TIMESTAMP, new String[] { OH_CHANNEL_LAST_UPDATE, GROUP_TIRES });
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,135 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.mercedesme.internal.utils;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.measure.Unit;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.mercedesme.internal.Constants;
|
||||
import org.openhab.core.library.unit.ImperialUnits;
|
||||
import org.openhab.core.library.unit.SIUnits;
|
||||
import org.openhab.core.library.unit.Units;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* {@link UOMObserver} responsible to identify Unit and StatePattern for a Mercedes VehicleAttribute
|
||||
*
|
||||
* @author Bernd Weymann - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class UOMObserver {
|
||||
// Values delivered by Mercedes API
|
||||
public static final String LENGTH_KM_UNIT = "KILOMETERS";
|
||||
public static final String LENGTH_MILES_UNIT = "MILES";
|
||||
public static final String SPEED_KM_UNIT = "KM_PER_HOUR";
|
||||
public static final String SPEED_MILES_UNIT = "M_PER_HOUR";
|
||||
public static final String CELSIUS_UNIT = "CELSIUS";
|
||||
public static final String FAHRENHEIT_UNIT = "FAHRENHEIT";
|
||||
public static final String BAR_UNIT = "BAR";
|
||||
public static final String PSI_UNIT = "PSI";
|
||||
public static final String KPA_UNIT = "KPA";
|
||||
public static final String CONSUMPTION_ELECTRIC_KM = "KM_PER_KWH";
|
||||
public static final String CONSUMPTION_ELECTRIC_MI = "M_PER_KWH";
|
||||
public static final String CONSUMPTION_ELECTRIC_100KM = "KWH_PER_100KM";
|
||||
public static final String CONSUMPTION_ELECTRIC_100MI = "KWH_PER_100MI";
|
||||
public static final String CONSUMPTION_LIQUID_100KM = "LITER_PER_100KM";
|
||||
public static final String CONSUMPTION_LIQUID_KM_PER_LITER = "KM_PER_LITER";
|
||||
public static final String CONSUMPTION_LIQUID_MPG_UK = "MPG_UK";
|
||||
public static final String CONSUMPTION_LIQUID_MPG_US = "MPG_US";
|
||||
public static final String CONSUMPTION_LIQUID_MI = "MPGE";
|
||||
public static final String CONSUMPTION_GAS_100KM = "KG_PER_100KM";
|
||||
public static final String TIME_US = "TIME_US";
|
||||
public static final String TIME_ROW = "TIME_ROW";
|
||||
|
||||
private static final Map<String, String> PATTERN_MAP = new HashMap<>();
|
||||
private static final Map<String, Unit<?>> UNIT_MAP = new HashMap<>();
|
||||
|
||||
private String label = Constants.NOT_SET;
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(UOMObserver.class);
|
||||
|
||||
public UOMObserver(String unitLabel) {
|
||||
if (PATTERN_MAP.isEmpty()) {
|
||||
PATTERN_MAP.put(LENGTH_KM_UNIT, "%.1f km");
|
||||
PATTERN_MAP.put(LENGTH_MILES_UNIT, "%.1f mi");
|
||||
PATTERN_MAP.put(SPEED_KM_UNIT, "%.0f km/h");
|
||||
PATTERN_MAP.put(SPEED_MILES_UNIT, "%.0f mph");
|
||||
PATTERN_MAP.put(CELSIUS_UNIT, "%.1f °C");
|
||||
PATTERN_MAP.put(FAHRENHEIT_UNIT, "%.0f °F");
|
||||
PATTERN_MAP.put(BAR_UNIT, "%.1f bar");
|
||||
PATTERN_MAP.put(KPA_UNIT, "%.1f kPa");
|
||||
PATTERN_MAP.put(PSI_UNIT, "%.1f psi");
|
||||
PATTERN_MAP.put(CONSUMPTION_ELECTRIC_KM, "km/kWh");
|
||||
PATTERN_MAP.put(CONSUMPTION_ELECTRIC_MI, "m/kWh");
|
||||
PATTERN_MAP.put(CONSUMPTION_ELECTRIC_100KM, "kWh/100km");
|
||||
PATTERN_MAP.put(CONSUMPTION_ELECTRIC_100MI, "kWh/100mi");
|
||||
PATTERN_MAP.put(CONSUMPTION_LIQUID_100KM, "l/100km");
|
||||
PATTERN_MAP.put(CONSUMPTION_LIQUID_KM_PER_LITER, "km/l");
|
||||
PATTERN_MAP.put(CONSUMPTION_LIQUID_MPG_UK, "mi/g");
|
||||
PATTERN_MAP.put(CONSUMPTION_LIQUID_MPG_US, "mi/g");
|
||||
PATTERN_MAP.put(CONSUMPTION_LIQUID_MI, "mpge");
|
||||
PATTERN_MAP.put(TIME_US, "%1$tA, %1$td.%1$tm. %1$tI:%1$tM %1$Tp");
|
||||
PATTERN_MAP.put(TIME_ROW, "%1$tA, %1$td.%1$tm. %1$tH:%1$tM");
|
||||
|
||||
UNIT_MAP.put(LENGTH_KM_UNIT, Constants.KILOMETRE_UNIT);
|
||||
UNIT_MAP.put(LENGTH_MILES_UNIT, ImperialUnits.MILE);
|
||||
UNIT_MAP.put(SPEED_KM_UNIT, SIUnits.KILOMETRE_PER_HOUR);
|
||||
UNIT_MAP.put(SPEED_MILES_UNIT, ImperialUnits.MILES_PER_HOUR);
|
||||
UNIT_MAP.put(CELSIUS_UNIT, SIUnits.CELSIUS);
|
||||
UNIT_MAP.put(FAHRENHEIT_UNIT, ImperialUnits.FAHRENHEIT);
|
||||
UNIT_MAP.put(BAR_UNIT, Units.BAR);
|
||||
UNIT_MAP.put(KPA_UNIT, Constants.KPA_UNIT);
|
||||
UNIT_MAP.put(PSI_UNIT, ImperialUnits.POUND_FORCE_SQUARE_INCH);
|
||||
UNIT_MAP.put(CONSUMPTION_ELECTRIC_KM, Constants.KILOWATT_HOUR_UNIT);
|
||||
UNIT_MAP.put(CONSUMPTION_ELECTRIC_MI, Constants.KILOWATT_HOUR_UNIT);
|
||||
UNIT_MAP.put(CONSUMPTION_ELECTRIC_100KM, Constants.KILOWATT_HOUR_UNIT);
|
||||
UNIT_MAP.put(CONSUMPTION_ELECTRIC_100MI, Constants.KILOWATT_HOUR_UNIT);
|
||||
UNIT_MAP.put(CONSUMPTION_LIQUID_100KM, Units.LITRE);
|
||||
UNIT_MAP.put(CONSUMPTION_LIQUID_MI, ImperialUnits.GALLON_LIQUID_US);
|
||||
}
|
||||
if (!PATTERN_MAP.containsKey(unitLabel)) {
|
||||
logger.trace("No mapping found for {}", unitLabel);
|
||||
}
|
||||
label = unitLabel;
|
||||
}
|
||||
|
||||
public String getLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Unit<?> getUnit() {
|
||||
return UNIT_MAP.get(label);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getPattern(String group, String channel) {
|
||||
String pattern = PATTERN_MAP.get(label);
|
||||
if (Constants.GROUP_RANGE.equals(group) && pattern != null) {
|
||||
if ("home-distance".equals(channel)) {
|
||||
return pattern.replace("1", "3");
|
||||
}
|
||||
return pattern.replace("1", "0");
|
||||
}
|
||||
return pattern;
|
||||
}
|
||||
|
||||
public boolean equals(UOMObserver compare) {
|
||||
return label.equals(compare.getLabel());
|
||||
}
|
||||
}
|
@ -0,0 +1,718 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.mercedesme.internal.utils;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Base64;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import javax.measure.Unit;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
import org.openhab.binding.mercedesme.internal.Constants;
|
||||
import org.openhab.binding.mercedesme.internal.MercedesMeHandlerFactory;
|
||||
import org.openhab.binding.mercedesme.internal.server.AuthService;
|
||||
import org.openhab.core.auth.client.oauth2.AccessTokenResponse;
|
||||
import org.openhab.core.i18n.LocaleProvider;
|
||||
import org.openhab.core.i18n.TimeZoneProvider;
|
||||
import org.openhab.core.library.types.DateTimeType;
|
||||
import org.openhab.core.library.unit.ImperialUnits;
|
||||
import org.openhab.core.library.unit.SIUnits;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.types.CommandOption;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.daimler.mbcarkit.proto.VehicleCommands.ChargeProgramConfigure.ChargeProgram;
|
||||
import com.daimler.mbcarkit.proto.VehicleCommands.TemperatureConfigure.TemperaturePoint.Zone;
|
||||
import com.daimler.mbcarkit.proto.VehicleEvents;
|
||||
import com.daimler.mbcarkit.proto.VehicleEvents.ChargeProgramParameters;
|
||||
import com.daimler.mbcarkit.proto.VehicleEvents.ChargeProgramsValue;
|
||||
import com.daimler.mbcarkit.proto.VehicleEvents.TemperaturePointsValue;
|
||||
import com.daimler.mbcarkit.proto.VehicleEvents.VEPUpdate;
|
||||
import com.daimler.mbcarkit.proto.VehicleEvents.VVRTimeProfile;
|
||||
import com.daimler.mbcarkit.proto.VehicleEvents.VehicleAttributeStatus;
|
||||
import com.daimler.mbcarkit.proto.VehicleEvents.WeeklyProfileValue;
|
||||
import com.daimler.mbcarkit.proto.VehicleEvents.WeeklySetting;
|
||||
import com.daimler.mbcarkit.proto.VehicleEvents.WeeklySettingsHeadUnitValue;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.protobuf.Descriptors.FieldDescriptor;
|
||||
|
||||
/**
|
||||
* {@link Utils} provides several helper functions used from different classes
|
||||
*
|
||||
* @author Bernd Weymann - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class Utils {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(Utils.class);
|
||||
private static final List<Integer> PORTS = new ArrayList<>();
|
||||
private static final List<CommandOption> FAHRENHEIT_COMMAND_OPTIONS = new ArrayList<>();
|
||||
private static final List<CommandOption> CELSIUS_COMMAND_OPTIONS = new ArrayList<>();
|
||||
|
||||
private static final int R = 6371; // Radius of the earth
|
||||
private static int port = 8090;
|
||||
private static TimeZoneProvider timeZoneProvider = new TimeZoneProvider() {
|
||||
@Override
|
||||
public ZoneId getTimeZone() {
|
||||
return ZoneId.systemDefault();
|
||||
}
|
||||
};
|
||||
private static LocaleProvider localeProvider = new LocaleProvider() {
|
||||
|
||||
@Override
|
||||
public Locale getLocale() {
|
||||
return Locale.getDefault();
|
||||
}
|
||||
};
|
||||
public static final Gson GSON = new Gson();
|
||||
public static final Map<String, Integer> ZONE_HASHMAP = new HashMap<>();
|
||||
public static final Map<String, Integer> PROGRAM_HASHMAP = new HashMap<>();
|
||||
|
||||
public static void initialize(TimeZoneProvider tzp, LocaleProvider lp) {
|
||||
timeZoneProvider = tzp;
|
||||
localeProvider = lp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getting openHAB DateTimeType from given milliseconds according to configured TimeZone
|
||||
*
|
||||
* @param ms - milliseconds in epoch milli
|
||||
* @return openHAB DateTimeType according to configured TimeZone
|
||||
*/
|
||||
public static DateTimeType getDateTimeType(long ms) {
|
||||
Instant timestamp = Instant.ofEpochMilli(ms);
|
||||
return new DateTimeType(timestamp.atZone(timeZoneProvider.getTimeZone()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the DateTime of charge end according to given Mercedes parameters
|
||||
*
|
||||
* @param ms - current timestamp in milliseconds in epoch milli
|
||||
* @param minutesAfterMidnight - minutes after midnight
|
||||
* @return calculates the start of day from given in ms plus minutes given in minutesAfterMidnight
|
||||
*/
|
||||
public static DateTimeType getEndOfChargeTime(long ms, long minutesAfterMidnight) {
|
||||
// get today midnight
|
||||
Instant timestamp = Instant.ofEpochMilli(ms);
|
||||
ZonedDateTime zdt = timestamp.atZone(timeZoneProvider.getTimeZone());
|
||||
ZonedDateTime endTime = zdt.withHour(0).withMinute(0).withSecond(0).plusMinutes(minutesAfterMidnight);
|
||||
return new DateTimeType(endTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get free port without other Thread interference from other AccountHandlers
|
||||
*
|
||||
* @return number of free port
|
||||
*/
|
||||
public static synchronized int getFreePort() {
|
||||
while (PORTS.contains(port)) {
|
||||
port++;
|
||||
}
|
||||
PORTS.add(port);
|
||||
return port;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register port for an AccountHandler
|
||||
*/
|
||||
public static synchronized void addPort(int portNr) {
|
||||
if (PORTS.contains(portNr) && portNr != 99999) {
|
||||
LOGGER.warn("Port {} already occupied", portNr);
|
||||
}
|
||||
PORTS.add(portNr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister port for an AccountHandler
|
||||
*/
|
||||
public static synchronized void removePort(int portNr) {
|
||||
PORTS.remove(Integer.valueOf(portNr));
|
||||
}
|
||||
|
||||
public static String getCallbackAddress(String callbackIP, int callbackPort) {
|
||||
return "http://" + callbackIP + Constants.COLON + callbackPort + Constants.CALLBACK_ENDPOINT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate REST API server address according to region
|
||||
*
|
||||
* @param region - configured region
|
||||
* @return base REST server address
|
||||
*/
|
||||
public static String getRestAPIServer(String region) {
|
||||
switch (region) {
|
||||
case Constants.REGION_APAC:
|
||||
return Constants.REST_API_BASE_PA;
|
||||
case Constants.REGION_CHINA:
|
||||
return Constants.REST_API_BASE_CN;
|
||||
case Constants.REGION_NORAM:
|
||||
return Constants.REST_API_BASE_NA;
|
||||
default:
|
||||
return Constants.REST_API_BASE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate Login API server address according to region
|
||||
*
|
||||
* @param region - configured region
|
||||
* @return base login server address
|
||||
*/
|
||||
public static String getLoginServer(String region) {
|
||||
switch (region) {
|
||||
case Constants.REGION_APAC:
|
||||
return Constants.LOGIN_BASE_URI_PA;
|
||||
case Constants.REGION_CHINA:
|
||||
return Constants.LOGIN_BASE_URI_CN;
|
||||
case Constants.REGION_NORAM:
|
||||
return Constants.LOGIN_BASE_URI_NA;
|
||||
default:
|
||||
return Constants.LOGIN_BASE_URI;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate websocket server address according to region
|
||||
*
|
||||
* @param region - configured region
|
||||
* @return websocket base server address
|
||||
*/
|
||||
public static String getWebsocketServer(String region) {
|
||||
switch (region) {
|
||||
case Constants.REGION_APAC:
|
||||
return Constants.WEBSOCKET_API_BASE_PA;
|
||||
case Constants.REGION_CHINA:
|
||||
return Constants.WEBSOCKET_API_BASE_CN;
|
||||
case Constants.REGION_NORAM:
|
||||
return Constants.WEBSOCKET_API_BASE_PA;
|
||||
default:
|
||||
return Constants.WEBSOCKET_API_BASE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate application name according to region
|
||||
*
|
||||
* @param region - configured region
|
||||
* @return application name as String
|
||||
*/
|
||||
public static String getApplication(String region) {
|
||||
switch (region) {
|
||||
case Constants.REGION_APAC:
|
||||
return Constants.X_APPLICATIONNAME_AP;
|
||||
case Constants.REGION_CHINA:
|
||||
return Constants.X_APPLICATIONNAME_CN;
|
||||
case Constants.REGION_NORAM:
|
||||
return Constants.X_APPLICATIONNAME_US;
|
||||
default:
|
||||
return Constants.X_APPLICATIONNAME;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate application version according to region
|
||||
*
|
||||
* @param region - configured region
|
||||
* @return application version as String
|
||||
*/
|
||||
public static String getRisApplicationVersion(String region) {
|
||||
switch (region) {
|
||||
case Constants.REGION_APAC:
|
||||
return Constants.RIS_APPLICATION_VERSION_PA;
|
||||
case Constants.REGION_CHINA:
|
||||
return Constants.RIS_APPLICATION_VERSION_CN;
|
||||
case Constants.REGION_NORAM:
|
||||
return Constants.RIS_APPLICATION_VERSION_NA;
|
||||
default:
|
||||
return Constants.RIS_APPLICATION_VERSION;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate user agent according to region
|
||||
*
|
||||
* @param region - configured region
|
||||
* @return user agent as String
|
||||
*/
|
||||
public static String getUserAgent(String region) {
|
||||
switch (region) {
|
||||
case Constants.REGION_APAC:
|
||||
return Constants.WEBSOCKET_USER_AGENT_PA;
|
||||
case Constants.REGION_CHINA:
|
||||
return Constants.WEBSOCKET_USER_AGENT_CN;
|
||||
default:
|
||||
return Constants.WEBSOCKET_USER_AGENT;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate SDK version according to region
|
||||
*
|
||||
* @param region - configured region
|
||||
* @return SDK version as String
|
||||
*/
|
||||
public static String getRisSDKVersion(String region) {
|
||||
switch (region) {
|
||||
case Constants.REGION_CHINA:
|
||||
return Constants.RIS_SDK_VERSION_CN;
|
||||
default:
|
||||
return Constants.RIS_SDK_VERSION;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate authorization config URL as pre-configuration prior to authorization call
|
||||
*
|
||||
* @param region - configured region
|
||||
* @return authorization config URL as String
|
||||
*/
|
||||
public static String getAuthConfigURL(String region) {
|
||||
return getRestAPIServer(region) + "/v1/config";
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate login app id according to region
|
||||
*
|
||||
* @param region - configured region
|
||||
* @return login app id as String
|
||||
*/
|
||||
public static String getLoginAppId(String region) {
|
||||
switch (region) {
|
||||
case Constants.REGION_CHINA:
|
||||
return Constants.LOGIN_APP_ID_CN;
|
||||
default:
|
||||
return Constants.LOGIN_APP_ID;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate authorization URL for authorization call
|
||||
*
|
||||
* @param region - configured region
|
||||
* @return authorization URL as String
|
||||
*/
|
||||
public static String getAuthURL(String region) {
|
||||
return getRestAPIServer(region) + "/v1/login";
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate token URL for getting token
|
||||
*
|
||||
* @param region - configured region
|
||||
* @return token URL as String
|
||||
*/
|
||||
public static String getTokenUrl(String region) {
|
||||
return getLoginServer(region) + "/as/token.oauth2";
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode String as Base64 from stored AccessTokenResponse
|
||||
*
|
||||
* @param token - Base64 String from storage
|
||||
* @return AccessTokenResponse decoded from String, invalid token otherwise
|
||||
*/
|
||||
public static AccessTokenResponse fromString(String token) {
|
||||
try {
|
||||
byte[] data = Base64.getDecoder().decode(token);
|
||||
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(data));
|
||||
Object o = ois.readObject();
|
||||
ois.close();
|
||||
return (AccessTokenResponse) o;
|
||||
} catch (IOException | ClassNotFoundException e) {
|
||||
LOGGER.warn("Error converting string to token {}", e.getMessage());
|
||||
}
|
||||
return AuthService.INVALID_TOKEN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode AccessTokenResponse as Base64 String for storage
|
||||
*
|
||||
* @param token - AccessTokenResponse to convert
|
||||
*/
|
||||
public static String toString(AccessTokenResponse token) {
|
||||
try {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
ObjectOutputStream oos = new ObjectOutputStream(baos);
|
||||
oos.writeObject(token);
|
||||
oos.close();
|
||||
return Base64.getEncoder().encodeToString(baos.toByteArray());
|
||||
} catch (IOException e) {
|
||||
LOGGER.warn("Error converting token to string {}", e.getMessage());
|
||||
}
|
||||
return Constants.NOT_SET;
|
||||
}
|
||||
|
||||
/**
|
||||
* Combine vehicle data maps which is needed for partial updates.
|
||||
* First take fullMap, then updates are taken from updateMap.
|
||||
*
|
||||
* @param fullMap - last present update of vehicle data
|
||||
* @param updateMap - updates to override
|
||||
* @return combined Map with updates taken into account
|
||||
*/
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public static Map combineMaps(Map fullMap, Map updateMap) {
|
||||
final Map combined = new TreeMap();
|
||||
fullMap.forEach((key, value) -> {
|
||||
combined.put(key, value);
|
||||
});
|
||||
updateMap.forEach((key, value) -> {
|
||||
combined.put(key, value);
|
||||
});
|
||||
return combined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a protobuf update into JSON String
|
||||
*
|
||||
* @param protoUpdate - proto update
|
||||
* @param uid - thing type uid for identification
|
||||
* @return JSON as String
|
||||
*/
|
||||
@SuppressWarnings({ "unused", "null" })
|
||||
public static String proto2Json(VEPUpdate protoUpdate, ThingTypeUID uid) {
|
||||
JSONObject protoJson = new JSONObject();
|
||||
Map<String, VehicleAttributeStatus> m = protoUpdate.getAttributesMap();
|
||||
m.forEach((key, value) -> {
|
||||
Map<FieldDescriptor, Object> attMap = value.getAllFields();
|
||||
JSONObject attributesJson = getJsonObject(attMap);
|
||||
|
||||
if (value.hasTemperaturePointsValue()) {
|
||||
TemperaturePointsValue tpv = value.getTemperaturePointsValue();
|
||||
JSONArray tmpPoints = new JSONArray();
|
||||
List<VehicleEvents.TemperaturePoint> temperaturePointsList = tpv.getTemperaturePointsList();
|
||||
temperaturePointsList.forEach(point -> {
|
||||
JSONObject tmpPoint = getJsonObject(point.getAllFields());
|
||||
tmpPoints.put(tmpPoint);
|
||||
});
|
||||
JSONObject points = new JSONObject();
|
||||
points.put("temperature_points", tmpPoints);
|
||||
attributesJson.put("temperature_points_value", points);
|
||||
} else if (value.hasChargeProgramsValue()) {
|
||||
ChargeProgramsValue cpv = value.getChargeProgramsValue();
|
||||
JSONArray chargeProgramArray = new JSONArray();
|
||||
List<ChargeProgramParameters> l = cpv.getChargeProgramParametersList();
|
||||
l.forEach(cpp -> {
|
||||
chargeProgramArray.put(getJsonObject(cpp.getAllFields()));
|
||||
});
|
||||
attributesJson.put("charge_programs_value", chargeProgramArray);
|
||||
} else if (value.hasWeeklyProfileValue()) {
|
||||
WeeklyProfileValue wpv = value.getWeeklyProfileValue();
|
||||
JSONObject weeklyProfiles = new JSONObject();
|
||||
List<VVRTimeProfile> timeProfilesList = wpv.getTimeProfilesList();
|
||||
timeProfilesList.forEach(timeProfileProto -> {
|
||||
JSONObject timeProfileJson = new JSONObject();
|
||||
JSONArray days = new JSONArray(timeProfileProto.getDaysList());
|
||||
timeProfileJson.put("days", days);
|
||||
timeProfileJson.put("hour", timeProfileProto.getHour());
|
||||
timeProfileJson.put("minute", timeProfileProto.getMinute());
|
||||
timeProfileJson.put("active", timeProfileProto.getActive());
|
||||
timeProfileJson.put("applicationIdentifier", timeProfileProto.getApplicationIdentifier());
|
||||
weeklyProfiles.put(Integer.toString(timeProfileProto.getIdentifier()), timeProfileJson);
|
||||
});
|
||||
attributesJson.put("weekly_profile_value", weeklyProfiles);
|
||||
} else if (value.hasWeeklySettingsHeadUnitValue()) {
|
||||
WeeklySettingsHeadUnitValue wshuv = value.getWeeklySettingsHeadUnitValue();
|
||||
List<WeeklySetting> valList = wshuv.getWeeklySettingsList();
|
||||
JSONArray settingsJsonArray = new JSONArray();
|
||||
valList.forEach(weeklySettingProto -> {
|
||||
JSONObject settings = new JSONObject();
|
||||
settings.put("day", weeklySettingProto.getDay());
|
||||
settings.put("minutes_since_midnight", weeklySettingProto.getMinutesSinceMidnight());
|
||||
settingsJsonArray.put(settings);
|
||||
});
|
||||
attributesJson.put("weekly_settings_head_unit_value", settingsJsonArray);
|
||||
}
|
||||
|
||||
// check for errors - in fact JSONObject returns null in case of errors
|
||||
if (attributesJson.toString() == null) {
|
||||
LOGGER.trace("JSON conversion failed for Proto {}", key);
|
||||
attributesJson = new JSONObject();
|
||||
attributesJson.put(key, attMap.toString());
|
||||
}
|
||||
if (attributesJson.toString() == null) {
|
||||
LOGGER.trace("JSON conversion failed for Map {}", key);
|
||||
attributesJson = new JSONObject();
|
||||
attributesJson.put(key, "Not supported by binding");
|
||||
}
|
||||
|
||||
// Anonymize position
|
||||
if ("positionLat".equals(key)) {
|
||||
attributesJson.put("double_value", 1.23);
|
||||
} else if ("positionLong".equals(key)) {
|
||||
attributesJson.put("double_value", 4.56);
|
||||
}
|
||||
protoJson.put(key, attributesJson);
|
||||
});
|
||||
// finally put binding version in
|
||||
JSONObject bindingInfo = new JSONObject();
|
||||
bindingInfo.put("version", Constants.BINDING_VERSION);
|
||||
bindingInfo.put("vehicle", uid.getAsString());
|
||||
bindingInfo.put("oh-bundle", MercedesMeHandlerFactory.getVersion());
|
||||
protoJson.put("bindingInfo", bindingInfo);
|
||||
return protoJson.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a proto Map with FieldDescriptor into a JSON Object
|
||||
*
|
||||
* @param attMap - proto attributes Map
|
||||
* @return JSONObject with key value pairs
|
||||
*/
|
||||
public static JSONObject getJsonObject(Map<FieldDescriptor, Object> attMap) {
|
||||
JSONObject joa = new JSONObject();
|
||||
attMap.forEach((aKey, aValue) -> {
|
||||
String[] bKey = aKey.toString().split("\\.");
|
||||
if (bKey.length > 1) {
|
||||
joa.put(bKey[bKey.length - 1], aValue);
|
||||
} else {
|
||||
joa.put(bKey[0], aValue.toString());
|
||||
}
|
||||
});
|
||||
return joa;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate zone number from 3rdparty generated proto files
|
||||
*
|
||||
* @param zone - zone definition as String
|
||||
* @return zone number for selection
|
||||
*/
|
||||
public static int getZoneNumber(String zone) {
|
||||
if (ZONE_HASHMAP.isEmpty()) {
|
||||
Zone[] zones = Zone.values();
|
||||
for (int i = 0; i < zones.length - 1; i++) {
|
||||
ZONE_HASHMAP.put(zones[i].name(), zones[i].getNumber());
|
||||
}
|
||||
}
|
||||
Integer zoneNumber = ZONE_HASHMAP.get(zone);
|
||||
if (zoneNumber != null) {
|
||||
return zoneNumber;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate charge program number from 3rdparty generated proto files
|
||||
*
|
||||
* @param program - charge program definition as String
|
||||
* @return charge program number for selection
|
||||
*/
|
||||
public static int getChargeProgramNumber(String program) {
|
||||
if (PROGRAM_HASHMAP.isEmpty()) {
|
||||
ChargeProgram[] programs = ChargeProgram.values();
|
||||
for (int i = 0; i < programs.length - 1; i++) {
|
||||
PROGRAM_HASHMAP.put(programs[i].name(), programs[i].getNumber());
|
||||
}
|
||||
}
|
||||
Integer programNumber = PROGRAM_HASHMAP.get(program);
|
||||
if (programNumber != null) {
|
||||
return programNumber;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate duration String from given minutes
|
||||
*
|
||||
* @param durationMinutes - duration in minutes
|
||||
* @return Sting in format days, hours and minutes
|
||||
*/
|
||||
public static String getDurationString(long durationMinutes) {
|
||||
if (durationMinutes < 0) {
|
||||
return "-1";
|
||||
}
|
||||
Duration duration = Duration.ofMinutes(durationMinutes);
|
||||
if (duration.toDaysPart() > 0) {
|
||||
return String.format("%sd %sh %sm", duration.toDaysPart(), duration.toHoursPart(),
|
||||
duration.toMinutesPart());
|
||||
} else if (duration.toHoursPart() > 0) {
|
||||
return String.format("%sh %sm", duration.toHoursPart(), duration.toMinutesPart());
|
||||
} else {
|
||||
return String.format("%sm", duration.toMinutesPart());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get int from proto VehicleAttributeStatus
|
||||
*
|
||||
* @param value - proto value
|
||||
* @return value as int, -1 otherwise
|
||||
*/
|
||||
public static int getInt(VehicleAttributeStatus value) {
|
||||
return Double.valueOf(getDouble(value)).intValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get double from proto VehicleAttributeStatus
|
||||
*
|
||||
* @param value - proto value
|
||||
* @return value as double, -1 otherwise
|
||||
*/
|
||||
public static double getDouble(@Nullable VehicleAttributeStatus value) {
|
||||
double ret = -1;
|
||||
if (value != null) {
|
||||
if (!isNil(value)) {
|
||||
if (value.getDisplayValue() != null) {
|
||||
if (value.getDisplayValue().strip().length() > 0) {
|
||||
try {
|
||||
return Double.valueOf(value.getDisplayValue());
|
||||
} catch (NumberFormatException nfe) {
|
||||
LOGGER.trace("Cannot transform Display Value {} into Double", value.getDisplayValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (value.hasDoubleValue()) {
|
||||
return value.getDoubleValue();
|
||||
} else if (value.hasIntValue()) {
|
||||
return value.getIntValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks proto VehicleAttributeStatus is nil
|
||||
*
|
||||
* @param value - proto value
|
||||
* @return true if nil value is present, false otherwise
|
||||
*/
|
||||
public static boolean isNil(@Nullable VehicleAttributeStatus value) {
|
||||
if (value != null) {
|
||||
if (value.hasNilValue()) {
|
||||
return value.getNilValue();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get country code from configured LocaleProvider
|
||||
*
|
||||
* @return country code
|
||||
*/
|
||||
public static String getCountry() {
|
||||
return localeProvider.getLocale().getCountry();
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate distance between two points in latitude and longitude taking
|
||||
* into account height difference. If you are not interested in height
|
||||
* difference pass 0.0. Uses Haversine method as its base.
|
||||
*
|
||||
* https://stackoverflow.com/questions/3694380/calculating-distance-between-two-points-using-latitude-longitude
|
||||
* lat1, lon1 Start point lat2, lon2 End point el1 Start altitude in meters
|
||||
* el2 End altitude in meters
|
||||
*
|
||||
* @returns Distance in Meters
|
||||
*/
|
||||
public static double distance(double lat1, double lat2, double lon1, double lon2, double el1, double el2) {
|
||||
double latDistance = Math.toRadians(lat2 - lat1);
|
||||
double lonDistance = Math.toRadians(lon2 - lon1);
|
||||
double a = Math.sin(latDistance / 2) * Math.sin(latDistance / 2) + Math.cos(Math.toRadians(lat1))
|
||||
* Math.cos(Math.toRadians(lat2)) * Math.sin(lonDistance / 2) * Math.sin(lonDistance / 2);
|
||||
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
||||
double distance = R * c * 1000; // convert to meters
|
||||
double height = el1 - el2;
|
||||
distance = Math.pow(distance, 2) + Math.pow(height, 2);
|
||||
return Math.sqrt(distance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates a list of CommandOptions for temperature settings which are also available in the Mercedes Me app
|
||||
*
|
||||
* @param unit - unit of temperature
|
||||
* @return List of CommandOptions, empty if unit isn't supported
|
||||
*/
|
||||
public static List<CommandOption> getTemperatureOptions(Unit<?> unit) {
|
||||
if (ImperialUnits.FAHRENHEIT.equals(unit)) {
|
||||
if (FAHRENHEIT_COMMAND_OPTIONS.isEmpty()) {
|
||||
FAHRENHEIT_COMMAND_OPTIONS.add(new CommandOption("60 °F", "60 °F"));
|
||||
FAHRENHEIT_COMMAND_OPTIONS.add(new CommandOption("61 °F", "61 °F"));
|
||||
FAHRENHEIT_COMMAND_OPTIONS.add(new CommandOption("62 °F", "62 °F"));
|
||||
FAHRENHEIT_COMMAND_OPTIONS.add(new CommandOption("63 °F", "63 °F"));
|
||||
FAHRENHEIT_COMMAND_OPTIONS.add(new CommandOption("64 °F", "64 °F"));
|
||||
FAHRENHEIT_COMMAND_OPTIONS.add(new CommandOption("65 °F", "65 °F"));
|
||||
FAHRENHEIT_COMMAND_OPTIONS.add(new CommandOption("66 °F", "66 °F"));
|
||||
FAHRENHEIT_COMMAND_OPTIONS.add(new CommandOption("67 °F", "67 °F"));
|
||||
FAHRENHEIT_COMMAND_OPTIONS.add(new CommandOption("68 °F", "68 °F"));
|
||||
FAHRENHEIT_COMMAND_OPTIONS.add(new CommandOption("69 °F", "69 °F"));
|
||||
FAHRENHEIT_COMMAND_OPTIONS.add(new CommandOption("70 °F", "70 °F"));
|
||||
FAHRENHEIT_COMMAND_OPTIONS.add(new CommandOption("71 °F", "71 °F"));
|
||||
FAHRENHEIT_COMMAND_OPTIONS.add(new CommandOption("72 °F", "72 °F"));
|
||||
FAHRENHEIT_COMMAND_OPTIONS.add(new CommandOption("73 °F", "73 °F"));
|
||||
FAHRENHEIT_COMMAND_OPTIONS.add(new CommandOption("74 °F", "74 °F"));
|
||||
FAHRENHEIT_COMMAND_OPTIONS.add(new CommandOption("75 °F", "75 °F"));
|
||||
FAHRENHEIT_COMMAND_OPTIONS.add(new CommandOption("76 °F", "76 °F"));
|
||||
FAHRENHEIT_COMMAND_OPTIONS.add(new CommandOption("77 °F", "77 °F"));
|
||||
FAHRENHEIT_COMMAND_OPTIONS.add(new CommandOption("78 °F", "78 °F"));
|
||||
FAHRENHEIT_COMMAND_OPTIONS.add(new CommandOption("79 °F", "79 °F"));
|
||||
FAHRENHEIT_COMMAND_OPTIONS.add(new CommandOption("80 °F", "80 °F"));
|
||||
FAHRENHEIT_COMMAND_OPTIONS.add(new CommandOption("81 °F", "81 °F"));
|
||||
FAHRENHEIT_COMMAND_OPTIONS.add(new CommandOption("82 °F", "82 °F"));
|
||||
FAHRENHEIT_COMMAND_OPTIONS.add(new CommandOption("83 °F", "83 °F"));
|
||||
FAHRENHEIT_COMMAND_OPTIONS.add(new CommandOption("84 °F", "84 °F"));
|
||||
}
|
||||
return FAHRENHEIT_COMMAND_OPTIONS;
|
||||
} else if (SIUnits.CELSIUS.equals(unit)) {
|
||||
if (CELSIUS_COMMAND_OPTIONS.isEmpty()) {
|
||||
CELSIUS_COMMAND_OPTIONS.add(new CommandOption("16 °C", "16 °C"));
|
||||
CELSIUS_COMMAND_OPTIONS.add(new CommandOption("16.5 °C", "16.5 °C"));
|
||||
CELSIUS_COMMAND_OPTIONS.add(new CommandOption("17 °C", "17 °C"));
|
||||
CELSIUS_COMMAND_OPTIONS.add(new CommandOption("17.5 °C", "17.5 °C"));
|
||||
CELSIUS_COMMAND_OPTIONS.add(new CommandOption("18 °C", "18 °C"));
|
||||
CELSIUS_COMMAND_OPTIONS.add(new CommandOption("18.5 °C", "18.5 °C"));
|
||||
CELSIUS_COMMAND_OPTIONS.add(new CommandOption("19 °C", "19 °C"));
|
||||
CELSIUS_COMMAND_OPTIONS.add(new CommandOption("19.5 °C", "19.5 °C"));
|
||||
CELSIUS_COMMAND_OPTIONS.add(new CommandOption("20 °C", "20 °C"));
|
||||
CELSIUS_COMMAND_OPTIONS.add(new CommandOption("20.5 °C", "20.5 °C"));
|
||||
CELSIUS_COMMAND_OPTIONS.add(new CommandOption("21 °C", "21 °C"));
|
||||
CELSIUS_COMMAND_OPTIONS.add(new CommandOption("21.5 °C", "21.5 °C"));
|
||||
CELSIUS_COMMAND_OPTIONS.add(new CommandOption("22 °C", "22 °C"));
|
||||
CELSIUS_COMMAND_OPTIONS.add(new CommandOption("22.5 °C", "22.5 °C"));
|
||||
CELSIUS_COMMAND_OPTIONS.add(new CommandOption("23 °C", "23 °C"));
|
||||
CELSIUS_COMMAND_OPTIONS.add(new CommandOption("23.5 °C", "23.5 °C"));
|
||||
CELSIUS_COMMAND_OPTIONS.add(new CommandOption("24 °C", "24 °C"));
|
||||
CELSIUS_COMMAND_OPTIONS.add(new CommandOption("24.5 °C", "24.5 °C"));
|
||||
CELSIUS_COMMAND_OPTIONS.add(new CommandOption("25 °C", "25 °C"));
|
||||
CELSIUS_COMMAND_OPTIONS.add(new CommandOption("25.5 °C", "25.5 °C"));
|
||||
CELSIUS_COMMAND_OPTIONS.add(new CommandOption("26 °C", "26 °C"));
|
||||
CELSIUS_COMMAND_OPTIONS.add(new CommandOption("26.5 °C", "26.5 °C"));
|
||||
CELSIUS_COMMAND_OPTIONS.add(new CommandOption("27 °C", "27 °C"));
|
||||
CELSIUS_COMMAND_OPTIONS.add(new CommandOption("27.5 °C", "27.5 °C"));
|
||||
CELSIUS_COMMAND_OPTIONS.add(new CommandOption("28 °C", "28 °C"));
|
||||
}
|
||||
return CELSIUS_COMMAND_OPTIONS;
|
||||
} else {
|
||||
return new ArrayList<CommandOption>();
|
||||
}
|
||||
}
|
||||
}
|
@ -8,50 +8,9 @@
|
||||
<parameter name="vin" type="text" required="true">
|
||||
<label>Vehicle Identification Number</label>
|
||||
</parameter>
|
||||
<parameter name="refreshInterval" type="integer" min="1" unit="min" required="true">
|
||||
<label>Refresh Interval</label>
|
||||
<description>Data refresh rate for vehicle data</description>
|
||||
<default>5</default>
|
||||
</parameter>
|
||||
<parameter name="batteryCapacity" type="decimal">
|
||||
<label>Battery Capacity</label>
|
||||
<description>Battery capacity in kWh of vehicle</description>
|
||||
</parameter>
|
||||
<!-- https://developer.mercedes-benz.com/products/vehicle_images/docs#_default_image_settings -->
|
||||
<parameter name="background" type="boolean">
|
||||
<label>Background Image</label>
|
||||
<description>Vehicle images provided with or without background</description>
|
||||
<default>false</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="night" type="boolean">
|
||||
<label>Night Image</label>
|
||||
<description>Vehicle images in night conditions</description>
|
||||
<default>false</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="cropped" type="boolean">
|
||||
<label>Cropped Image</label>
|
||||
<description>Vehicle images in 4:3 instead of 16:9</description>
|
||||
<default>false</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="roofOpen" type="boolean">
|
||||
<label>Cabriolet Open Roof</label>
|
||||
<description>Vehicle images with open roof (only Cabriolet)</description>
|
||||
<default>false</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="format" type="text">
|
||||
<label>Image Format</label>
|
||||
<description>Preferred Image Format</description>
|
||||
<default>webp</default>
|
||||
<advanced>true</advanced>
|
||||
<options>
|
||||
<option value="webp">webp</option>
|
||||
<option value="png">png</option>
|
||||
<option value="jpeg">jpeg</option>
|
||||
</options>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</config-description:config-descriptions>
|
||||
|
@ -5,42 +5,29 @@
|
||||
xsi:schemaLocation="https://openhab.org/schemas/config-description/v1.0.0 https://openhab.org/schemas/config-description-1.0.0.xsd">
|
||||
|
||||
<config-description uri="thing-type:mercedesme:bridge">
|
||||
<parameter name="clientId" type="text" required="true">
|
||||
<label>MB Developer Client ID</label>
|
||||
<description>Mercedes Benz Developer Client ID</description>
|
||||
<parameter name="email" type="text" required="true">
|
||||
<label>MercedesMe EMail</label>
|
||||
<description>EMail address for MercedesMe account</description>
|
||||
<context>email</context>
|
||||
</parameter>
|
||||
<parameter name="clientSecret" type="text" required="true">
|
||||
<label>MB Developer Client Secret</label>
|
||||
<description>Mercedes Benz Developer Client Secret</description>
|
||||
<parameter name="region" type="text" required="true">
|
||||
<label>Region</label>
|
||||
<options>
|
||||
<option value="EU">Europe</option>
|
||||
<option value="NA">North America</option>
|
||||
<option value="AP">Asia-Pacific</option>
|
||||
<option value="CN">China</option>
|
||||
</options>
|
||||
</parameter>
|
||||
<parameter name="imageApiKey" type="text">
|
||||
<label>MB Developer Image API Key</label>
|
||||
<description>Mercedes Benz Developer Image API Key</description>
|
||||
<parameter name="pin" type="text" required="false">
|
||||
<label>PIN</label>
|
||||
<description>PIN for commands</description>
|
||||
<context>password</context>
|
||||
</parameter>
|
||||
<parameter name="odoScope" type="boolean">
|
||||
<label>PayAsYourDrive Insurance</label>
|
||||
<description>Provides total Mileage</description>
|
||||
<default>true</default>
|
||||
</parameter>
|
||||
<parameter name="vehicleScope" type="boolean">
|
||||
<label>Vehicle Status</label>
|
||||
<description>Status of doors, windows lights</description>
|
||||
<default>true</default>
|
||||
</parameter>
|
||||
<parameter name="lockScope" type="boolean">
|
||||
<label>Vehicle Lock Status</label>
|
||||
<description>Lock status of doors and trunk</description>
|
||||
<default>true</default>
|
||||
</parameter>
|
||||
<parameter name="fuelScope" type="boolean">
|
||||
<label>Fuel Status</label>
|
||||
<description>Tank level and range</description>
|
||||
<default>true</default>
|
||||
</parameter>
|
||||
<parameter name="evScope" type="boolean">
|
||||
<label>Electric Vehicle Status</label>
|
||||
<description>Electric charge and range</description>
|
||||
<default>true</default>
|
||||
<parameter name="refreshInterval" type="integer" min="5" unit="min" required="true">
|
||||
<label>Refresh Interval</label>
|
||||
<description>Refresh Interval in Minutes</description>
|
||||
<default>15</default>
|
||||
</parameter>
|
||||
<parameter name="callbackIP" type="text">
|
||||
<label>Callback IP Address</label>
|
||||
|
@ -8,50 +8,9 @@
|
||||
<parameter name="vin" type="text" required="true">
|
||||
<label>Vehicle Identification Number</label>
|
||||
</parameter>
|
||||
<parameter name="refreshInterval" type="integer" min="1" unit="min" required="true">
|
||||
<label>Refresh Interval</label>
|
||||
<description>Data refresh rate for your vehicle data</description>
|
||||
<default>5</default>
|
||||
</parameter>
|
||||
<parameter name="fuelCapacity" type="decimal" min="0">
|
||||
<label>Fuel Capacity</label>
|
||||
<description>Fuel capacity in liters of vehicle</description>
|
||||
</parameter>
|
||||
<!-- https://developer.mercedes-benz.com/products/vehicle_images/docs#_default_image_settings -->
|
||||
<parameter name="background" type="boolean">
|
||||
<label>Background Image</label>
|
||||
<description>Vehicle images provided with or without background</description>
|
||||
<default>false</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="night" type="boolean">
|
||||
<label>Night Image</label>
|
||||
<description>Vehicle images in night conditions</description>
|
||||
<default>false</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="cropped" type="boolean">
|
||||
<label>Cropped Image</label>
|
||||
<description>Vehicle images in 4:3 instead of 16:9</description>
|
||||
<default>false</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="roofOpen" type="boolean">
|
||||
<label>Cabriolet Open Roof</label>
|
||||
<description>Vehicle images with open roof (only Cabriolet)</description>
|
||||
<default>false</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="format" type="text">
|
||||
<label>Image Format</label>
|
||||
<description>Preferred Image Format</description>
|
||||
<default>webp</default>
|
||||
<advanced>true</advanced>
|
||||
<options>
|
||||
<option value="webp">webp</option>
|
||||
<option value="png">png</option>
|
||||
<option value="jpeg">jpeg</option>
|
||||
</options>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</config-description:config-descriptions>
|
||||
|
@ -8,11 +8,6 @@
|
||||
<parameter name="vin" type="text" required="true">
|
||||
<label>Vehicle Identification Number</label>
|
||||
</parameter>
|
||||
<parameter name="refreshInterval" type="integer" min="1" unit="min" required="true">
|
||||
<label>Refresh Interval</label>
|
||||
<description>Data refresh rate for vehicle data</description>
|
||||
<default>5</default>
|
||||
</parameter>
|
||||
<parameter name="batteryCapacity" type="decimal">
|
||||
<label>Battery Capacity</label>
|
||||
<description>Battery capacity in kWh of vehicle</description>
|
||||
@ -21,41 +16,5 @@
|
||||
<label>Fuel Capacity</label>
|
||||
<description>Fuel capacity in liters of vehicle</description>
|
||||
</parameter>
|
||||
<!-- https://developer.mercedes-benz.com/products/vehicle_images/docs#_default_image_settings -->
|
||||
<parameter name="background" type="boolean">
|
||||
<label>Background Image</label>
|
||||
<description>Vehicle images provided with or without background</description>
|
||||
<default>false</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="night" type="boolean">
|
||||
<label>Night Image</label>
|
||||
<description>Vehicle images in night conditions</description>
|
||||
<default>false</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="cropped" type="boolean">
|
||||
<label>Cropped Image</label>
|
||||
<description>Vehicle images in 4:3 instead of 16:9</description>
|
||||
<default>false</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="roofOpen" type="boolean">
|
||||
<label>Cabriolet Open Roof</label>
|
||||
<description>Vehicle images with open roof (only Cabriolet)</description>
|
||||
<default>false</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="format" type="text">
|
||||
<label>Image Format</label>
|
||||
<description>Preferred Image Format</description>
|
||||
<default>webp</default>
|
||||
<advanced>true</advanced>
|
||||
<options>
|
||||
<option value="webp">webp</option>
|
||||
<option value="png">png</option>
|
||||
<option value="jpeg">jpeg</option>
|
||||
</options>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</config-description:config-descriptions>
|
||||
|
@ -16,203 +16,300 @@ thing-type.mercedesme.hybrid.description = Conventional Fuel Vehicle with suppor
|
||||
|
||||
# thing types config
|
||||
|
||||
thing-type.config.mercedesme.bev.background.label = Background Image
|
||||
thing-type.config.mercedesme.bev.background.description = Vehicle images provided with or without background
|
||||
thing-type.config.mercedesme.bev.batteryCapacity.label = Battery Capacity
|
||||
thing-type.config.mercedesme.bev.batteryCapacity.description = Battery capacity in kwh of vehicle
|
||||
thing-type.config.mercedesme.bev.cropped.label = Cropped Image
|
||||
thing-type.config.mercedesme.bev.cropped.description = Vehicle images in 4:3 instead of 16:9
|
||||
thing-type.config.mercedesme.bev.format.label = Image Format
|
||||
thing-type.config.mercedesme.bev.format.description = Preferred Image Format
|
||||
thing-type.config.mercedesme.bev.format.option.webp = webp
|
||||
thing-type.config.mercedesme.bev.format.option.png = png
|
||||
thing-type.config.mercedesme.bev.format.option.jpeg = jpeg
|
||||
thing-type.config.mercedesme.bev.night.label = Night Image
|
||||
thing-type.config.mercedesme.bev.night.description = Vehicle images in night conditions
|
||||
thing-type.config.mercedesme.bev.refreshInterval.label = Refresh Interval
|
||||
thing-type.config.mercedesme.bev.refreshInterval.description = Data refresh rate for vehicle data
|
||||
thing-type.config.mercedesme.bev.roofOpen.label = Cabriolet Open Roof
|
||||
thing-type.config.mercedesme.bev.roofOpen.description = Vehicle images with open roof (only Cabriolet)
|
||||
thing-type.config.mercedesme.bev.batteryCapacity.description = Battery capacity in kWh of vehicle
|
||||
thing-type.config.mercedesme.bev.vin.label = Vehicle Identification Number
|
||||
thing-type.config.mercedesme.bridge.callbackIP.label = Callback IP Address
|
||||
thing-type.config.mercedesme.bridge.callbackIP.description = IP address for openHAB callback URL
|
||||
thing-type.config.mercedesme.bridge.callbackPort.label = Callback Port Number
|
||||
thing-type.config.mercedesme.bridge.callbackPort.description = Port Number for openHAB callback URL
|
||||
thing-type.config.mercedesme.bridge.clientId.label = MB Developer Client ID
|
||||
thing-type.config.mercedesme.bridge.clientId.description = Mercedes Benz Developer Client ID
|
||||
thing-type.config.mercedesme.bridge.clientSecret.label = MB Developer Client Secret
|
||||
thing-type.config.mercedesme.bridge.clientSecret.description = Mercedes Benz Developer Client Secret
|
||||
thing-type.config.mercedesme.bridge.evScope.label = Electric Vehicle Status
|
||||
thing-type.config.mercedesme.bridge.evScope.description = Electric charge and range
|
||||
thing-type.config.mercedesme.bridge.fuelScope.label = Fuel Status
|
||||
thing-type.config.mercedesme.bridge.fuelScope.description = Tank level and range
|
||||
thing-type.config.mercedesme.bridge.imageApiKey.label = MB Developer Image API Key
|
||||
thing-type.config.mercedesme.bridge.imageApiKey.description = Mercedes Benz Developer Image API Key
|
||||
thing-type.config.mercedesme.bridge.lockScope.label = Vehicle Lock Status
|
||||
thing-type.config.mercedesme.bridge.lockScope.description = Lock status of doors and trunk
|
||||
thing-type.config.mercedesme.bridge.odoScope.label = PayAsYourDrive Insurance
|
||||
thing-type.config.mercedesme.bridge.odoScope.description = Provides total Mileage
|
||||
thing-type.config.mercedesme.bridge.vehicleScope.label = Vehicle Status
|
||||
thing-type.config.mercedesme.bridge.vehicleScope.description = Status of doors, windows lights
|
||||
thing-type.config.mercedesme.conv.background.label = Background Image
|
||||
thing-type.config.mercedesme.conv.background.description = Vehicle images provided with or without background
|
||||
thing-type.config.mercedesme.conv.cropped.label = Cropped Image
|
||||
thing-type.config.mercedesme.conv.cropped.description = Vehicle images in 4:3 instead of 16:9
|
||||
thing-type.config.mercedesme.conv.format.label = Image Format
|
||||
thing-type.config.mercedesme.conv.format.description = Preferred Image Format
|
||||
thing-type.config.mercedesme.conv.format.option.webp = webp
|
||||
thing-type.config.mercedesme.conv.format.option.png = png
|
||||
thing-type.config.mercedesme.conv.format.option.jpeg = jpeg
|
||||
thing-type.config.mercedesme.bridge.email.label = MercedesMe EMail
|
||||
thing-type.config.mercedesme.bridge.email.description = EMail address for MercedesMe account
|
||||
thing-type.config.mercedesme.bridge.pin.label = PIN
|
||||
thing-type.config.mercedesme.bridge.pin.description = PIN for commands
|
||||
thing-type.config.mercedesme.bridge.refreshInterval.label = Refresh Interval
|
||||
thing-type.config.mercedesme.bridge.refreshInterval.description = Refresh Interval in Minutes
|
||||
thing-type.config.mercedesme.bridge.region.label = Region
|
||||
thing-type.config.mercedesme.bridge.region.option.EU = Europe
|
||||
thing-type.config.mercedesme.bridge.region.option.NA = North America
|
||||
thing-type.config.mercedesme.bridge.region.option.AP = Asia-Pacific
|
||||
thing-type.config.mercedesme.bridge.region.option.CN = China
|
||||
thing-type.config.mercedesme.conv.fuelCapacity.label = Fuel Capacity
|
||||
thing-type.config.mercedesme.conv.fuelCapacity.description = Fuel capacity in liters of vehicle
|
||||
thing-type.config.mercedesme.conv.night.label = Night Image
|
||||
thing-type.config.mercedesme.conv.night.description = Vehicle images in night conditions
|
||||
thing-type.config.mercedesme.conv.refreshInterval.label = Refresh Interval
|
||||
thing-type.config.mercedesme.conv.refreshInterval.description = Data refresh rate for your vehicle data
|
||||
thing-type.config.mercedesme.conv.roofOpen.label = Cabriolet Open Roof
|
||||
thing-type.config.mercedesme.conv.roofOpen.description = Vehicle images with open roof (only Cabriolet)
|
||||
thing-type.config.mercedesme.conv.vin.label = Vehicle Identification Number
|
||||
thing-type.config.mercedesme.hybrid.background.label = Background Image
|
||||
thing-type.config.mercedesme.hybrid.background.description = Vehicle images provided with or without background
|
||||
thing-type.config.mercedesme.hybrid.batteryCapacity.label = Battery Capacity
|
||||
thing-type.config.mercedesme.hybrid.batteryCapacity.description = Battery capacity in kwh of vehicle
|
||||
thing-type.config.mercedesme.hybrid.cropped.label = Cropped Image
|
||||
thing-type.config.mercedesme.hybrid.cropped.description = Vehicle images in 4:3 instead of 16:9
|
||||
thing-type.config.mercedesme.hybrid.format.label = Image Format
|
||||
thing-type.config.mercedesme.hybrid.format.description = Preferred Image Format
|
||||
thing-type.config.mercedesme.hybrid.format.option.webp = webp
|
||||
thing-type.config.mercedesme.hybrid.format.option.png = png
|
||||
thing-type.config.mercedesme.hybrid.format.option.jpeg = jpeg
|
||||
thing-type.config.mercedesme.hybrid.batteryCapacity.description = Battery capacity in kWh of vehicle
|
||||
thing-type.config.mercedesme.hybrid.fuelCapacity.label = Fuel Capacity
|
||||
thing-type.config.mercedesme.hybrid.fuelCapacity.description = Fuel capacity in liters of vehicle
|
||||
thing-type.config.mercedesme.hybrid.night.label = Night Image
|
||||
thing-type.config.mercedesme.hybrid.night.description = Vehicle images in night conditions
|
||||
thing-type.config.mercedesme.hybrid.refreshInterval.label = Refresh Interval
|
||||
thing-type.config.mercedesme.hybrid.refreshInterval.description = Data refresh rate for vehicle data
|
||||
thing-type.config.mercedesme.hybrid.roofOpen.label = Cabriolet Open Roof
|
||||
thing-type.config.mercedesme.hybrid.roofOpen.description = Vehicle images with open roof (only Cabriolet)
|
||||
thing-type.config.mercedesme.hybrid.vin.label = Vehicle Identification Number
|
||||
|
||||
# channel group types
|
||||
|
||||
channel-group-type.mercedesme.charge-values.label = Charging Data
|
||||
channel-group-type.mercedesme.command-values.label = Status of Last Command
|
||||
channel-group-type.mercedesme.door-values.label = Detailed Door Status
|
||||
channel-group-type.mercedesme.door-values.description = Detailed Status of all Doors and Windows
|
||||
channel-group-type.mercedesme.image-values.label = Vehicle Images
|
||||
channel-group-type.mercedesme.light-values.label = Light Status
|
||||
channel-group-type.mercedesme.light-values.description = Light Status of interior lights and main light switch
|
||||
channel-group-type.mercedesme.location-values.label = Vehicle Location
|
||||
channel-group-type.mercedesme.location-values.description = Heading of vehicle
|
||||
channel-group-type.mercedesme.hvac-values.label = Vehicle Climate Control
|
||||
channel-group-type.mercedesme.lock-ev-values.label = Lock Status
|
||||
channel-group-type.mercedesme.lock-ev-values.description = Door Lock Status
|
||||
channel-group-type.mercedesme.lock-values.label = Lock Status
|
||||
channel-group-type.mercedesme.lock-values.description = Vehicle Lock Status
|
||||
channel-group-type.mercedesme.lock-values.description = Door Lock Status
|
||||
channel-group-type.mercedesme.position-values.label = Vehicle Location
|
||||
channel-group-type.mercedesme.position-values.description = Heading of vehicle
|
||||
channel-group-type.mercedesme.range-conv-values.label = Range and Fuel Data
|
||||
channel-group-type.mercedesme.range-conv-values.description = Provides Mileage, remaining range and fuel level values
|
||||
channel-group-type.mercedesme.range-ev-values.label = Range and Charge Data
|
||||
channel-group-type.mercedesme.range-ev-values.label = Range and Battery Data
|
||||
channel-group-type.mercedesme.range-ev-values.description = Provides Mileage, remaining range and charge level values
|
||||
channel-group-type.mercedesme.range-hybrid-values.label = Range, Charge / Fuel Data
|
||||
channel-group-type.mercedesme.range-hybrid-values.label = Range, Battery and Fuel Data
|
||||
channel-group-type.mercedesme.range-hybrid-values.description = Provides mileage, remaining fuel and range data for hybrid vehicles
|
||||
channel-group-type.mercedesme.service-ev-values.label = Service and Warnings
|
||||
channel-group-type.mercedesme.service-values.label = Warnings
|
||||
channel-group-type.mercedesme.service-values.description = Current active warnings
|
||||
channel-group-type.mercedesme.tires-values.label = Tire Status
|
||||
channel-group-type.mercedesme.tires-values.description = Tire Pressure Values
|
||||
channel-group-type.mercedesme.trip-conv-values.label = Last Trip Data
|
||||
channel-group-type.mercedesme.trip-ev-values.label = Last Trip Data
|
||||
channel-group-type.mercedesme.trip-hybrid-values.label = Last Trip Data
|
||||
channel-group-type.mercedesme.vehicle-values.label = Vehicle Status
|
||||
channel-group-type.mercedesme.vehicle-values.description = General vehicle status data
|
||||
channel-group-type.mercedesme.window-values.label = Detailed Window Status
|
||||
channel-group-type.mercedesme.window-values.description = Detailed Status Windows
|
||||
|
||||
# channel types
|
||||
|
||||
channel-type.mercedesme.charged-channel.label = Charged Battery Energy
|
||||
channel-type.mercedesme.clear-cache-channel.label = Remove All Stored Images
|
||||
channel-type.mercedesme.deck-lid-channel.label = Deck Lid
|
||||
channel-type.mercedesme.deck-lid-lock-channel.label = Deck Lid Lock
|
||||
channel-type.mercedesme.doors-lock-channel.label = Door Lock Status
|
||||
channel-type.mercedesme.doors-lock-channel.state.option.0 = Unlocked
|
||||
channel-type.mercedesme.doors-lock-channel.state.option.1 = Locked Internal
|
||||
channel-type.mercedesme.doors-lock-channel.state.option.2 = Locked External
|
||||
channel-type.mercedesme.doors-lock-channel.state.option.3 = Unlocked Selective
|
||||
channel-type.mercedesme.driver-front-channel.label = Driver Door
|
||||
channel-type.mercedesme.driver-rear-channel.label = Driver Door Rear
|
||||
channel-type.mercedesme.flap-lock-channel.label = Flap Lock
|
||||
channel-type.mercedesme.fuel-level-channel.label = Fuel Level
|
||||
channel-type.mercedesme.fuel-open-channel.label = Open Fuel Capacity
|
||||
channel-type.mercedesme.fuel-remain-channel.label = Remaining Fuel
|
||||
channel-type.mercedesme.heading-channel.label = Heading Angle
|
||||
channel-type.mercedesme.image-data-channel.label = Rendered Vehicle Image
|
||||
channel-type.mercedesme.image-view-channel.label = Image Viewport
|
||||
channel-type.mercedesme.interior-front-channel.label = Interior Light Front
|
||||
channel-type.mercedesme.interior-rear-channel.label = Interior Light Rear
|
||||
channel-type.mercedesme.last-doors-update-channel.label = Last Doors Update
|
||||
channel-type.mercedesme.last-doors-update-channel.state.pattern = %1$tA, %1$td.%1$tm. %1$tH:%1$tM
|
||||
channel-type.mercedesme.last-lights-update-channel.label = Last Light Update
|
||||
channel-type.mercedesme.last-lights-update-channel.state.pattern = %1$tA, %1$td.%1$tm. %1$tH:%1$tM
|
||||
channel-type.mercedesme.last-location-update-channel.label = Last Location Update
|
||||
channel-type.mercedesme.last-location-update-channel.state.pattern = %1$tA, %1$td.%1$tm. %1$tH:%1$tM
|
||||
channel-type.mercedesme.last-lock-update-channel.label = Last Lock Update
|
||||
channel-type.mercedesme.last-lock-update-channel.state.pattern = %1$tA, %1$td.%1$tm. %1$tH:%1$tM
|
||||
channel-type.mercedesme.last-range-update-channel.label = Last Range Update
|
||||
channel-type.mercedesme.last-range-update-channel.state.pattern = %1$tA, %1$td.%1$tm. %1$tH:%1$tM
|
||||
channel-type.mercedesme.last-windows-update-channel.label = Last Window Update
|
||||
channel-type.mercedesme.last-windows-update-channel.state.pattern = %1$tA, %1$td.%1$tm. %1$tH:%1$tM
|
||||
channel-type.mercedesme.light-switch-channel.label = Main Light Rotary
|
||||
channel-type.mercedesme.light-switch-channel.state.option.0 = Auto
|
||||
channel-type.mercedesme.light-switch-channel.state.option.1 = Headlight
|
||||
channel-type.mercedesme.light-switch-channel.state.option.2 = Sidelight Left
|
||||
channel-type.mercedesme.light-switch-channel.state.option.3 = Sidelight Right
|
||||
channel-type.mercedesme.light-switch-channel.state.option.4 = Parking Light
|
||||
channel-type.mercedesme.mileage-channel.label = Mileage
|
||||
channel-type.mercedesme.passenger-front-channel.label = Passenger Door
|
||||
channel-type.mercedesme.passenger-rear-channel.label = Passenger Door Rear
|
||||
channel-type.mercedesme.radius-electric-channel.label = Electric Radius
|
||||
channel-type.mercedesme.radius-fuel-channel.label = Fuel Radius
|
||||
channel-type.mercedesme.radius-hybrid-channel.label = Hybrid Radius
|
||||
channel-type.mercedesme.range-electric-channel.label = Electric Range
|
||||
channel-type.mercedesme.range-fuel-channel.label = Fuel Range
|
||||
channel-type.mercedesme.range-hybrid-channel.label = Hybrid Range
|
||||
channel-type.mercedesme.reading-left-channel.label = Reading Light Left
|
||||
channel-type.mercedesme.reading-right-channel.label = Reading Light Right
|
||||
channel-type.mercedesme.rooftop-channel.label = Roof top
|
||||
channel-type.mercedesme.rooftop-channel.state.option.0 = Unlocked
|
||||
channel-type.mercedesme.rooftop-channel.state.option.1 = Open and locked
|
||||
channel-type.mercedesme.rooftop-channel.state.option.2 = Closed and locked
|
||||
channel-type.mercedesme.soc-channel.label = Battery Charge Level
|
||||
channel-type.mercedesme.sunroof-channel.label = Sun Roof
|
||||
channel-type.mercedesme.sunroof-channel.state.option.0 = Closed
|
||||
channel-type.mercedesme.sunroof-channel.state.option.1 = Open
|
||||
channel-type.mercedesme.sunroof-channel.state.option.2 = Open Lifting
|
||||
channel-type.mercedesme.sunroof-channel.state.option.3 = Running
|
||||
channel-type.mercedesme.sunroof-channel.state.option.4 = Closing
|
||||
channel-type.mercedesme.sunroof-channel.state.option.5 = Opening
|
||||
channel-type.mercedesme.sunroof-channel.state.option.6 = Closing
|
||||
channel-type.mercedesme.uncharged-channel.label = Uncharged Battery Energy
|
||||
channel-type.mercedesme.window-driver-front-channel.label = Driver Window
|
||||
channel-type.mercedesme.window-driver-front-channel.state.option.0 = Intermediate
|
||||
channel-type.mercedesme.window-driver-front-channel.state.option.1 = Open
|
||||
channel-type.mercedesme.window-driver-front-channel.state.option.2 = Closed
|
||||
channel-type.mercedesme.window-driver-front-channel.state.option.3 = Airing
|
||||
channel-type.mercedesme.window-driver-front-channel.state.option.4 = Intermediate
|
||||
channel-type.mercedesme.window-driver-front-channel.state.option.5 = Running
|
||||
channel-type.mercedesme.window-driver-rear-channel.label = Driver Window Rear
|
||||
channel-type.mercedesme.window-driver-rear-channel.state.option.0 = Intermediate
|
||||
channel-type.mercedesme.window-driver-rear-channel.state.option.1 = Open
|
||||
channel-type.mercedesme.window-driver-rear-channel.state.option.2 = Closed
|
||||
channel-type.mercedesme.window-driver-rear-channel.state.option.3 = Airing
|
||||
channel-type.mercedesme.window-driver-rear-channel.state.option.4 = Intermediate
|
||||
channel-type.mercedesme.window-driver-rear-channel.state.option.5 = Running
|
||||
channel-type.mercedesme.window-passenger-front-channel.label = Passenger Window
|
||||
channel-type.mercedesme.window-passenger-front-channel.state.option.0 = Intermediate
|
||||
channel-type.mercedesme.window-passenger-front-channel.state.option.1 = Open
|
||||
channel-type.mercedesme.window-passenger-front-channel.state.option.2 = Closed
|
||||
channel-type.mercedesme.window-passenger-front-channel.state.option.3 = Airing
|
||||
channel-type.mercedesme.window-passenger-front-channel.state.option.4 = Intermediate
|
||||
channel-type.mercedesme.window-passenger-front-channel.state.option.5 = Running
|
||||
channel-type.mercedesme.window-passenger-rear-channel.label = Passenger Window Rear
|
||||
channel-type.mercedesme.window-passenger-rear-channel.state.option.0 = Intermediate
|
||||
channel-type.mercedesme.window-passenger-rear-channel.state.option.1 = Open
|
||||
channel-type.mercedesme.window-passenger-rear-channel.state.option.2 = Closed
|
||||
channel-type.mercedesme.window-passenger-rear-channel.state.option.3 = Airing
|
||||
channel-type.mercedesme.window-passenger-rear-channel.state.option.4 = Intermediate
|
||||
channel-type.mercedesme.window-passenger-rear-channel.state.option.5 = Running
|
||||
channel-type.mercedesme.active-hvac.label = AC Control
|
||||
channel-type.mercedesme.active.label = Charge Active
|
||||
channel-type.mercedesme.auto-unlock.label = Coupler Auto Unlock
|
||||
channel-type.mercedesme.auto-unlock.description = Auto unlock coupler after charging
|
||||
channel-type.mercedesme.aux-heat.label = Auxiliary Heating Control
|
||||
channel-type.mercedesme.avg-speed-reset.label = Rst Average Speed
|
||||
channel-type.mercedesme.avg-speed-reset.description = Average speed since last Reset
|
||||
channel-type.mercedesme.avg-speed.label = Trip Average Speed
|
||||
channel-type.mercedesme.brake-fluid.label = Brake Fluid
|
||||
channel-type.mercedesme.brake-lining-wear.label = Brake Lining Wear
|
||||
channel-type.mercedesme.charge-flap.label = Charge Flap
|
||||
channel-type.mercedesme.charge-flap.description = Charge Flap Status
|
||||
channel-type.mercedesme.charge-flap.state.option.0 = Open
|
||||
channel-type.mercedesme.charge-flap.state.option.1 = Closed
|
||||
channel-type.mercedesme.charged.label = Charged Battery Energy
|
||||
channel-type.mercedesme.cmd-last-update.label = Command Updated
|
||||
channel-type.mercedesme.cmd-last-update.state.pattern = %1$tA, %1$td.%1$tm. %1$tH:%1$tM
|
||||
channel-type.mercedesme.cmd-name.label = Command Name
|
||||
channel-type.mercedesme.cmd-state.label = Command State
|
||||
channel-type.mercedesme.command-capabilities.label = Command Capabilities
|
||||
channel-type.mercedesme.consumption-conv-reset.label = Avg Cons Rst Fuel
|
||||
channel-type.mercedesme.consumption-conv-reset.description = Average consumption since last reset fuel
|
||||
channel-type.mercedesme.consumption-conv-unit.label = Avg Cons Unit Fuel
|
||||
channel-type.mercedesme.consumption-conv-unit.description = Average consumption unit fuel
|
||||
channel-type.mercedesme.consumption-conv.label = Trip Avg Cons Fuel
|
||||
channel-type.mercedesme.consumption-conv.description = Last Trip Average Consumption Fuel
|
||||
channel-type.mercedesme.consumption-ev-reset.label = Avg Cons Rst EV
|
||||
channel-type.mercedesme.consumption-ev-reset.description = Average consumption since last reset electric
|
||||
channel-type.mercedesme.consumption-ev-unit.label = Avg Cons Unit EV
|
||||
channel-type.mercedesme.consumption-ev-unit.description = Average consumption unit electric
|
||||
channel-type.mercedesme.consumption-ev.label = Trip Avg Cons EV
|
||||
channel-type.mercedesme.consumption-ev.description = Last Trip Average Consumption Electric
|
||||
channel-type.mercedesme.coolant-fluid.label = Coolant Fluid Low
|
||||
channel-type.mercedesme.coupler-ac.label = Charge Coupler AC
|
||||
channel-type.mercedesme.coupler-ac.description = Coupler AC Status
|
||||
channel-type.mercedesme.coupler-ac.state.option.0 = Plugged
|
||||
channel-type.mercedesme.coupler-ac.state.option.2 = Unplugged
|
||||
channel-type.mercedesme.coupler-dc.label = Charge Coupler DC
|
||||
channel-type.mercedesme.coupler-dc.description = Coupler DC Status
|
||||
channel-type.mercedesme.coupler-dc.state.option.0 = Plugged
|
||||
channel-type.mercedesme.coupler-dc.state.option.2 = Unplugged
|
||||
channel-type.mercedesme.coupler-lock.label = Charge Coupler Lock
|
||||
channel-type.mercedesme.coupler-lock.description = Coupler Lock Status
|
||||
channel-type.mercedesme.coupler-lock.state.option.0 = Locked
|
||||
channel-type.mercedesme.coupler-lock.state.option.1 = Unlocked
|
||||
channel-type.mercedesme.deck-lid-lock.label = Deck Lid Lock
|
||||
channel-type.mercedesme.deck-lid.label = Deck Lid
|
||||
channel-type.mercedesme.distance-reset.label = Rst Distance
|
||||
channel-type.mercedesme.distance-reset.description = Distance since last Reset
|
||||
channel-type.mercedesme.distance.label = Trip Distance
|
||||
channel-type.mercedesme.door-status.label = Door Status
|
||||
channel-type.mercedesme.door-status.state.option.0 = Open
|
||||
channel-type.mercedesme.door-status.state.option.1 = Closed
|
||||
channel-type.mercedesme.driven-time-reset.label = Rst Driving Time
|
||||
channel-type.mercedesme.driven-time-reset.description = Driving time since last Reset
|
||||
channel-type.mercedesme.driven-time.label = Trip String Time
|
||||
channel-type.mercedesme.end-time.label = Charge End Estimation
|
||||
channel-type.mercedesme.end-time.state.pattern = %1$tH:%1$tM
|
||||
channel-type.mercedesme.engine-hood.label = Engine Hood
|
||||
channel-type.mercedesme.engine.label = Engine Warning
|
||||
channel-type.mercedesme.feature-capabilities.label = Feature Capabilities
|
||||
channel-type.mercedesme.flip-window.label = Flip Window
|
||||
channel-type.mercedesme.front-left-hvac.label = AC Seat Front Left
|
||||
channel-type.mercedesme.front-left-lock.label = Door Lock Front Left
|
||||
channel-type.mercedesme.front-left-window.label = Window Front Left
|
||||
channel-type.mercedesme.front-left-window.state.option.0 = Intermediate
|
||||
channel-type.mercedesme.front-left-window.state.option.1 = Open
|
||||
channel-type.mercedesme.front-left-window.state.option.2 = Closed
|
||||
channel-type.mercedesme.front-left-window.state.option.3 = Airing
|
||||
channel-type.mercedesme.front-left-window.state.option.4 = Intermediate
|
||||
channel-type.mercedesme.front-left-window.state.option.5 = Running
|
||||
channel-type.mercedesme.front-left.label = Door Front Left
|
||||
channel-type.mercedesme.front-right-hvac.label = AC Seat Front Right
|
||||
channel-type.mercedesme.front-right-lock.label = Door Lock Front Right
|
||||
channel-type.mercedesme.front-right-window.label = Window Front Right
|
||||
channel-type.mercedesme.front-right-window.state.option.0 = Intermediate
|
||||
channel-type.mercedesme.front-right-window.state.option.1 = Open
|
||||
channel-type.mercedesme.front-right-window.state.option.2 = Closed
|
||||
channel-type.mercedesme.front-right-window.state.option.3 = Airing
|
||||
channel-type.mercedesme.front-right-window.state.option.4 = Intermediate
|
||||
channel-type.mercedesme.front-right-window.state.option.5 = Running
|
||||
channel-type.mercedesme.front-right.label = Door Front Right
|
||||
channel-type.mercedesme.fuel-level.label = Fuel Level
|
||||
channel-type.mercedesme.fuel-open.label = Open Fuel Capacity
|
||||
channel-type.mercedesme.fuel-remain.label = Remaining Fuel
|
||||
channel-type.mercedesme.gas-flap-lock.label = Flap Lock
|
||||
channel-type.mercedesme.gps.label = Position GPS
|
||||
channel-type.mercedesme.heading.label = Position Heading Angle
|
||||
channel-type.mercedesme.home-distance.label = Distance to Home
|
||||
channel-type.mercedesme.ignition.label = Ignition
|
||||
channel-type.mercedesme.ignition.state.option.0 = Lock
|
||||
channel-type.mercedesme.ignition.state.option.1 = Off
|
||||
channel-type.mercedesme.ignition.state.option.2 = Accessory
|
||||
channel-type.mercedesme.ignition.state.option.4 = On
|
||||
channel-type.mercedesme.ignition.state.option.5 = Start
|
||||
channel-type.mercedesme.ignition.command.option.0 = Off
|
||||
channel-type.mercedesme.ignition.command.option.4 = On
|
||||
channel-type.mercedesme.last-update.label = Tire Update Time
|
||||
channel-type.mercedesme.last-update.state.pattern = %1$tA, %1$td.%1$tm. %1$tH:%1$tM
|
||||
channel-type.mercedesme.lock.label = Lock Status/Control
|
||||
channel-type.mercedesme.lock.state.option.0 = Locked
|
||||
channel-type.mercedesme.lock.state.option.1 = Unlocked
|
||||
channel-type.mercedesme.lock.command.option.0 = Lock
|
||||
channel-type.mercedesme.lock.command.option.1 = Unlock
|
||||
channel-type.mercedesme.marker-front-left.label = Tire Warning Front Left
|
||||
channel-type.mercedesme.marker-front-left.state.option.0 = No warning
|
||||
channel-type.mercedesme.marker-front-left.state.option.1 = Soft warning
|
||||
channel-type.mercedesme.marker-front-left.state.option.2 = Low warning
|
||||
channel-type.mercedesme.marker-front-left.state.option.3 = Deflation
|
||||
channel-type.mercedesme.marker-front-left.state.option.4 = Unknown warning
|
||||
channel-type.mercedesme.marker-front-right.label = Tire Warning Front Right
|
||||
channel-type.mercedesme.marker-front-right.state.option.0 = No warning
|
||||
channel-type.mercedesme.marker-front-right.state.option.1 = Soft warning
|
||||
channel-type.mercedesme.marker-front-right.state.option.2 = Low warning
|
||||
channel-type.mercedesme.marker-front-right.state.option.3 = Deflation
|
||||
channel-type.mercedesme.marker-front-right.state.option.4 = Unknown warning
|
||||
channel-type.mercedesme.marker-rear-left.label = Tire Warning Rear Left
|
||||
channel-type.mercedesme.marker-rear-left.state.option.0 = No warning
|
||||
channel-type.mercedesme.marker-rear-left.state.option.1 = Soft warning
|
||||
channel-type.mercedesme.marker-rear-left.state.option.2 = Low warning
|
||||
channel-type.mercedesme.marker-rear-left.state.option.3 = Deflation
|
||||
channel-type.mercedesme.marker-rear-left.state.option.4 = Unknown warning
|
||||
channel-type.mercedesme.marker-rear-right.label = Tire Warning Rear Right
|
||||
channel-type.mercedesme.marker-rear-right.state.option.0 = No warning
|
||||
channel-type.mercedesme.marker-rear-right.state.option.1 = Soft warning
|
||||
channel-type.mercedesme.marker-rear-right.state.option.2 = Low warning
|
||||
channel-type.mercedesme.marker-rear-right.state.option.3 = Deflation
|
||||
channel-type.mercedesme.marker-rear-right.state.option.4 = Unknown warning
|
||||
channel-type.mercedesme.max-soc.label = Charge SoC Maximum
|
||||
channel-type.mercedesme.max-soc.command.option.50 % = 50 %
|
||||
channel-type.mercedesme.max-soc.command.option.60 % = 60 %
|
||||
channel-type.mercedesme.max-soc.command.option.70 % = 70 %
|
||||
channel-type.mercedesme.max-soc.command.option.80 % = 80 %
|
||||
channel-type.mercedesme.max-soc.command.option.90 % = 90 %
|
||||
channel-type.mercedesme.max-soc.command.option.100 % = 100 %
|
||||
channel-type.mercedesme.mileage.label = Mileage
|
||||
channel-type.mercedesme.park-brake.label = Park Brake Active
|
||||
channel-type.mercedesme.power.label = Charge Power
|
||||
channel-type.mercedesme.pressure-front-left.label = Tire Pressure Front Left
|
||||
channel-type.mercedesme.pressure-front-right.label = Tire Pressure Front Right
|
||||
channel-type.mercedesme.pressure-rear-left.label = Tire Pressure Rear Left
|
||||
channel-type.mercedesme.pressure-rear-right.label = Tire Pressure Rear Right
|
||||
channel-type.mercedesme.program.label = Charge Program
|
||||
channel-type.mercedesme.program.description = Selected Charge Program
|
||||
channel-type.mercedesme.proto-update.label = Proto Data Update
|
||||
channel-type.mercedesme.radius-electric.label = Electric Radius
|
||||
channel-type.mercedesme.radius-fuel.label = Fuel Radius
|
||||
channel-type.mercedesme.radius-hybrid.label = Hybrid Radius
|
||||
channel-type.mercedesme.range-electric.label = Electric Range
|
||||
channel-type.mercedesme.range-fuel.label = Fuel Range
|
||||
channel-type.mercedesme.range-hybrid.label = Hybrid Range
|
||||
channel-type.mercedesme.rear-blind.label = Window Blind Rear
|
||||
channel-type.mercedesme.rear-left-blind.label = Window Blind Rear Left
|
||||
channel-type.mercedesme.rear-left-hvac.label = AC Seat Rear Left
|
||||
channel-type.mercedesme.rear-left-lock.label = Door Lock Rear Left
|
||||
channel-type.mercedesme.rear-left-window.label = Window Rear Left
|
||||
channel-type.mercedesme.rear-left-window.state.option.0 = Intermediate
|
||||
channel-type.mercedesme.rear-left-window.state.option.1 = Open
|
||||
channel-type.mercedesme.rear-left-window.state.option.2 = Closed
|
||||
channel-type.mercedesme.rear-left-window.state.option.3 = Airing
|
||||
channel-type.mercedesme.rear-left-window.state.option.4 = Intermediate
|
||||
channel-type.mercedesme.rear-left-window.state.option.5 = Running
|
||||
channel-type.mercedesme.rear-left.label = Door Rear Left
|
||||
channel-type.mercedesme.rear-right-blind.label = Window Blind Rear Right
|
||||
channel-type.mercedesme.rear-right-hvac.label = AC Seat Rear Right
|
||||
channel-type.mercedesme.rear-right-lock.label = Door Lock Rear Right
|
||||
channel-type.mercedesme.rear-right-window.label = Window Rear Right
|
||||
channel-type.mercedesme.rear-right-window.state.option.0 = Intermediate
|
||||
channel-type.mercedesme.rear-right-window.state.option.1 = Open
|
||||
channel-type.mercedesme.rear-right-window.state.option.2 = Closed
|
||||
channel-type.mercedesme.rear-right-window.state.option.3 = Airing
|
||||
channel-type.mercedesme.rear-right-window.state.option.4 = Intermediate
|
||||
channel-type.mercedesme.rear-right-window.state.option.5 = Running
|
||||
channel-type.mercedesme.rear-right.label = Door Rear Right
|
||||
channel-type.mercedesme.rooftop.label = Roof top
|
||||
channel-type.mercedesme.rooftop.state.option.0 = Unlocked
|
||||
channel-type.mercedesme.rooftop.state.option.1 = Open and locked
|
||||
channel-type.mercedesme.rooftop.state.option.2 = Closed and locked
|
||||
channel-type.mercedesme.sensor-available.label = Tire Sensor Available
|
||||
channel-type.mercedesme.service-days.label = Service in Days
|
||||
channel-type.mercedesme.signal.label = Position Signal
|
||||
channel-type.mercedesme.signal.state.option.0 = Position Lights
|
||||
channel-type.mercedesme.signal.state.option.1 = Position Horn
|
||||
channel-type.mercedesme.signal.command.option.0 = Position Lights
|
||||
channel-type.mercedesme.signal.command.option.1 = Position Horn
|
||||
channel-type.mercedesme.soc.label = Battery Charge Level
|
||||
channel-type.mercedesme.starter-battery.label = Starter Battery Status
|
||||
channel-type.mercedesme.starter-battery.state.option.0 = Green
|
||||
channel-type.mercedesme.starter-battery.state.option.1 = Yellow
|
||||
channel-type.mercedesme.starter-battery.state.option.2 = Red
|
||||
channel-type.mercedesme.sunroof-front-blind.label = Sun Roof Front Blind
|
||||
channel-type.mercedesme.sunroof-rear-blind.label = Sun Roof Rear Blind
|
||||
channel-type.mercedesme.sunroof.label = Sun Roof
|
||||
channel-type.mercedesme.sunroof.state.option.0 = Closed
|
||||
channel-type.mercedesme.sunroof.state.option.1 = Open
|
||||
channel-type.mercedesme.sunroof.state.option.2 = Lifted
|
||||
channel-type.mercedesme.sunroof.state.option.3 = Running
|
||||
channel-type.mercedesme.sunroof.state.option.4 = Closing
|
||||
channel-type.mercedesme.sunroof.state.option.5 = Opening
|
||||
channel-type.mercedesme.sunroof.state.option.6 = Closing
|
||||
channel-type.mercedesme.sunroof.command.option.0 = Close
|
||||
channel-type.mercedesme.sunroof.command.option.1 = Open
|
||||
channel-type.mercedesme.sunroof.command.option.2 = Lift
|
||||
channel-type.mercedesme.temperature-hvac.label = AC Temperature
|
||||
channel-type.mercedesme.tires-rdk.label = Tire Pressure Warnings
|
||||
channel-type.mercedesme.uncharged.label = Uncharged Battery Energy
|
||||
channel-type.mercedesme.wash-water.label = Wash Water Low
|
||||
channel-type.mercedesme.windows.label = Windows Status/Control
|
||||
channel-type.mercedesme.windows.state.option.0 = Intermediate
|
||||
channel-type.mercedesme.windows.state.option.1 = Closed
|
||||
channel-type.mercedesme.windows.state.option.2 = Open
|
||||
channel-type.mercedesme.windows.command.option.0 = Ventilate
|
||||
channel-type.mercedesme.windows.command.option.1 = Close
|
||||
channel-type.mercedesme.windows.command.option.2 = Open
|
||||
channel-type.mercedesme.zone-hvac.label = AC Zone
|
||||
|
||||
# MercedesMe Things Status Details
|
||||
# channel types
|
||||
|
||||
actionPoiLabel = Send POI to Vehicle
|
||||
actionPoiDescription = Send POI with name, latitude and longitude
|
||||
poiTitle = POI Name
|
||||
poiTitleDescription = Name of the location
|
||||
latitudeLabel = Latitude
|
||||
latitudeDescription = Latitude of the location
|
||||
longitudeLabel = Longitude
|
||||
longitudeDescription = Longitude of the location
|
||||
mercedesme.account.status.authorization-needed = Manual Authorization needed at {0}
|
||||
mercedesme.account.status.email-missing = EMail missing
|
||||
mercedesme.account.status.region-missing = Region missing
|
||||
mercedesme.account.status.refresh-invalid = Refresh Interval Invalid
|
||||
mercedesme.account.status.ip-missing = Callback IP missing
|
||||
mercedesme.account.status.port-missing = Callback Port missing
|
||||
mercedesme.account.status.client-id-missing = Client ID missing
|
||||
mercedesme.account.status.client-secret-missing = Client Secret missing
|
||||
mercedesme.account.status.server-restart = Disable and enable Bridge to restart Authorization Server
|
||||
mercedesme.vehicle.status.bridge-missing = Bridge not set
|
||||
mercedesme.vehicle.status.bridge-authoriziation = Check Bridge Authorization
|
||||
mercedesme.account.status.ip-autodetect-failure = Callback IP cannot be detected
|
||||
mercedesme.account.status.websocket-failure = Websocket Exception: Reason: {0}
|
||||
|
@ -0,0 +1,90 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="mercedesme"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
<channel-type id="charge-flap">
|
||||
<item-type>Number</item-type>
|
||||
<label>Charge Flap</label>
|
||||
<description>Charge Flap Status</description>
|
||||
<state readOnly="true">
|
||||
<options>
|
||||
<option value="0">Open</option>
|
||||
<option value="1">Closed</option>
|
||||
</options>
|
||||
</state>
|
||||
</channel-type>
|
||||
<channel-type id="coupler-ac">
|
||||
<item-type>Number</item-type>
|
||||
<label>Charge Coupler AC</label>
|
||||
<description>Coupler AC Status</description>
|
||||
<state readOnly="true">
|
||||
<options>
|
||||
<option value="0">Plugged</option>
|
||||
<option value="2">Unplugged</option>
|
||||
</options>
|
||||
</state>
|
||||
</channel-type>
|
||||
<channel-type id="coupler-dc">
|
||||
<item-type>Number</item-type>
|
||||
<label>Charge Coupler DC</label>
|
||||
<description>Coupler DC Status</description>
|
||||
<state readOnly="true">
|
||||
<options>
|
||||
<option value="0">Plugged</option>
|
||||
<option value="2">Unplugged</option>
|
||||
</options>
|
||||
</state>
|
||||
</channel-type>
|
||||
<channel-type id="coupler-lock">
|
||||
<item-type>Number</item-type>
|
||||
<label>Charge Coupler Lock</label>
|
||||
<description>Coupler Lock Status</description>
|
||||
<state readOnly="true">
|
||||
<options>
|
||||
<option value="0">Locked</option>
|
||||
<option value="1">Unlocked</option>
|
||||
</options>
|
||||
</state>
|
||||
</channel-type>
|
||||
<channel-type id="active">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Charge Active</label>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="power">
|
||||
<item-type>Number:Power</item-type>
|
||||
<label>Charge Power</label>
|
||||
<state pattern="%.1f kW" readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="program">
|
||||
<item-type>Number</item-type>
|
||||
<label>Charge Program</label>
|
||||
<description>Selected Charge Program</description>
|
||||
</channel-type>
|
||||
<channel-type id="end-time">
|
||||
<item-type>DateTime</item-type>
|
||||
<label>Charge End Estimation</label>
|
||||
<state pattern="%1$tH:%1$tM" readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="max-soc">
|
||||
<item-type>Number:Dimensionless</item-type>
|
||||
<label>Charge SoC Maximum</label>
|
||||
<state pattern="%d %%"/>
|
||||
<command>
|
||||
<options>
|
||||
<option value="50 %">50 %</option>
|
||||
<option value="60 %">60 %</option>
|
||||
<option value="70 %">70 %</option>
|
||||
<option value="80 %">80 %</option>
|
||||
<option value="90 %">90 %</option>
|
||||
<option value="100 %">100 %</option>
|
||||
</options>
|
||||
</command>
|
||||
</channel-type>
|
||||
<channel-type id="auto-unlock">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Coupler Auto Unlock</label>
|
||||
<description>Auto unlock coupler after charging </description>
|
||||
</channel-type>
|
||||
</thing:thing-descriptions>
|
@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="mercedesme"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
<channel-group-type id="charge-values">
|
||||
<label>Charging Data</label>
|
||||
<channels>
|
||||
<channel id="charge-flap" typeId="charge-flap"/>
|
||||
<channel id="coupler-ac" typeId="coupler-ac"/>
|
||||
<channel id="coupler-dc" typeId="coupler-dc"/>
|
||||
<channel id="coupler-lock" typeId="coupler-lock"/>
|
||||
<channel id="active" typeId="active"/>
|
||||
<channel id="power" typeId="power"/>
|
||||
<channel id="end-time" typeId="end-time"/>
|
||||
<channel id="program" typeId="program"/>
|
||||
<channel id="max-soc" typeId="max-soc"/>
|
||||
<channel id="auto-unlock" typeId="auto-unlock"/>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
</thing:thing-descriptions>
|
@ -3,14 +3,19 @@
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
<channel-type id="heading-channel">
|
||||
<item-type>Number:Angle</item-type>
|
||||
<label>Heading Angle</label>
|
||||
<state pattern="%d %unit%" readOnly="true"/>
|
||||
<channel-type id="cmd-name">
|
||||
<item-type>Number</item-type>
|
||||
<label>Command Name</label>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="last-location-update-channel">
|
||||
<channel-type id="cmd-state">
|
||||
<item-type>Number</item-type>
|
||||
<label>Command State</label>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="cmd-last-update">
|
||||
<item-type>DateTime</item-type>
|
||||
<label>Last Location Update</label>
|
||||
<label>Command Updated</label>
|
||||
<state pattern="%1$tA, %1$td.%1$tm. %1$tH:%1$tM" readOnly="true"/>
|
||||
</channel-type>
|
||||
</thing:thing-descriptions>
|
@ -3,12 +3,12 @@
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
<channel-group-type id="image-values">
|
||||
<label>Vehicle Images</label>
|
||||
<channel-group-type id="command-values">
|
||||
<label>Status of Last Command</label>
|
||||
<channels>
|
||||
<channel id="image-data" typeId="image-data-channel"/>
|
||||
<channel id="image-view" typeId="image-view-channel"/>
|
||||
<channel id="clear-cache" typeId="clear-cache-channel"/>
|
||||
<channel id="cmd-name" typeId="cmd-name"/>
|
||||
<channel id="cmd-state" typeId="cmd-state"/>
|
||||
<channel id="cmd-last-update" typeId="cmd-last-update"/>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
</thing:thing-descriptions>
|
@ -3,32 +3,37 @@
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
<channel-type id="driver-front-channel">
|
||||
<channel-type id="front-left">
|
||||
<item-type>Contact</item-type>
|
||||
<label>Driver Door</label>
|
||||
<label>Door Front Left</label>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="driver-rear-channel">
|
||||
<channel-type id="front-right">
|
||||
<item-type>Contact</item-type>
|
||||
<label>Driver Door Rear</label>
|
||||
<label>Door Front Right</label>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="passenger-front-channel">
|
||||
<channel-type id="rear-left">
|
||||
<item-type>Contact</item-type>
|
||||
<label>Passenger Door</label>
|
||||
<label>Door Rear Left</label>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="passenger-rear-channel">
|
||||
<channel-type id="rear-right">
|
||||
<item-type>Contact</item-type>
|
||||
<label>Passenger Door Rear</label>
|
||||
<label>Door Rear Right</label>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="deck-lid-channel">
|
||||
<channel-type id="deck-lid">
|
||||
<item-type>Contact</item-type>
|
||||
<label>Deck Lid</label>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="rooftop-channel">
|
||||
<channel-type id="engine-hood">
|
||||
<item-type>Contact</item-type>
|
||||
<label>Engine Hood</label>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="rooftop">
|
||||
<item-type>Number</item-type>
|
||||
<label>Roof top</label>
|
||||
<state readOnly="true">
|
||||
@ -39,24 +44,37 @@
|
||||
</options>
|
||||
</state>
|
||||
</channel-type>
|
||||
<channel-type id="sunroof-channel">
|
||||
<channel-type id="sunroof">
|
||||
<item-type>Number</item-type>
|
||||
<label>Sun Roof</label>
|
||||
<state readOnly="true">
|
||||
<state>
|
||||
<options>
|
||||
<option value="0">Closed</option>
|
||||
<option value="1">Open</option>
|
||||
<option value="2">Open Lifting</option>
|
||||
<option value="2">Lifted</option>
|
||||
<option value="3">Running</option>
|
||||
<option value="4">Closing</option>
|
||||
<option value="5">Opening</option>
|
||||
<option value="6">Closing</option>
|
||||
</options>
|
||||
</state>
|
||||
<command>
|
||||
<options>
|
||||
<option value="0">Close</option>
|
||||
<option value="1">Open</option>
|
||||
<option value="2">Lift</option>
|
||||
</options>
|
||||
</command>
|
||||
<autoUpdatePolicy>veto</autoUpdatePolicy>
|
||||
</channel-type>
|
||||
<channel-type id="last-doors-update-channel">
|
||||
<item-type>DateTime</item-type>
|
||||
<label>Last Doors Update</label>
|
||||
<state pattern="%1$tA, %1$td.%1$tm. %1$tH:%1$tM" readOnly="true"/>
|
||||
<channel-type id="sunroof-front-blind">
|
||||
<item-type>Number</item-type>
|
||||
<label>Sun Roof Front Blind</label>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="sunroof-rear-blind">
|
||||
<item-type>Number</item-type>
|
||||
<label>Sun Roof Rear Blind</label>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
</thing:thing-descriptions>
|
||||
|
@ -7,14 +7,16 @@
|
||||
<label>Detailed Door Status</label>
|
||||
<description>Detailed Status of all Doors and Windows</description>
|
||||
<channels>
|
||||
<channel id="driver-front" typeId="driver-front-channel"/>
|
||||
<channel id="driver-rear" typeId="driver-rear-channel"/>
|
||||
<channel id="passenger-front" typeId="passenger-front-channel"/>
|
||||
<channel id="passenger-rear" typeId="passenger-rear-channel"/>
|
||||
<channel id="deck-lid" typeId="deck-lid-channel"/>
|
||||
<channel id="sunroof" typeId="sunroof-channel"/>
|
||||
<channel id="rooftop" typeId="rooftop-channel"/>
|
||||
<channel id="last-update" typeId="last-doors-update-channel"/>
|
||||
<channel id="front-left" typeId="front-left"/>
|
||||
<channel id="front-right" typeId="front-right"/>
|
||||
<channel id="rear-left" typeId="rear-left"/>
|
||||
<channel id="rear-right" typeId="rear-right"/>
|
||||
<channel id="deck-lid" typeId="deck-lid"/>
|
||||
<channel id="engine-hood" typeId="engine-hood"/>
|
||||
<channel id="rooftop" typeId="rooftop"/>
|
||||
<channel id="sunroof" typeId="sunroof"/>
|
||||
<channel id="sunroof-front-blind" typeId="sunroof-front-blind"/>
|
||||
<channel id="sunroof-rear-blind" typeId="sunroof-rear-blind"/>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
</thing:thing-descriptions>
|
||||
|
@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="mercedesme"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
<channel-type id="zone-hvac">
|
||||
<item-type>Number</item-type>
|
||||
<label>AC Zone</label>
|
||||
<autoUpdatePolicy>veto</autoUpdatePolicy>
|
||||
</channel-type>
|
||||
<channel-type id="temperature-hvac">
|
||||
<item-type>Number:Temperature</item-type>
|
||||
<label>AC Temperature</label>
|
||||
<autoUpdatePolicy>veto</autoUpdatePolicy>
|
||||
</channel-type>
|
||||
<channel-type id="active-hvac">
|
||||
<item-type>Switch</item-type>
|
||||
<label>AC Control</label>
|
||||
<autoUpdatePolicy>veto</autoUpdatePolicy>
|
||||
</channel-type>
|
||||
<channel-type id="front-left-hvac">
|
||||
<item-type>Switch</item-type>
|
||||
<label>AC Seat Front Left</label>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="front-right-hvac">
|
||||
<item-type>Switch</item-type>
|
||||
<label>AC Seat Front Right</label>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="rear-left-hvac">
|
||||
<item-type>Switch</item-type>
|
||||
<label>AC Seat Rear Left</label>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="rear-right-hvac">
|
||||
<item-type>Switch</item-type>
|
||||
<label>AC Seat Rear Right</label>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="aux-heat">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Auxiliary Heating Control</label>
|
||||
<autoUpdatePolicy>veto</autoUpdatePolicy>
|
||||
</channel-type>
|
||||
</thing:thing-descriptions>
|
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="mercedesme"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
<channel-group-type id="hvac-values">
|
||||
<label>Vehicle Climate Control</label>
|
||||
<channels>
|
||||
<channel id="front-left" typeId="front-left-hvac"/>
|
||||
<channel id="front-right" typeId="front-right-hvac"/>
|
||||
<channel id="rear-left" typeId="rear-left-hvac"/>
|
||||
<channel id="rear-right" typeId="rear-right-hvac"/>
|
||||
<channel id="zone" typeId="zone-hvac"/>
|
||||
<channel id="temperature" typeId="temperature-hvac"/>
|
||||
<channel id="active" typeId="active-hvac"/>
|
||||
<channel id="aux-heat" typeId="aux-heat"/>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
</thing:thing-descriptions>
|
@ -1,19 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="mercedesme"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
<channel-type id="image-data-channel">
|
||||
<item-type>Image</item-type>
|
||||
<label>Rendered Vehicle Image</label>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="image-view-channel">
|
||||
<item-type>String</item-type>
|
||||
<label>Image Viewport</label>
|
||||
</channel-type>
|
||||
<channel-type id="clear-cache-channel">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Remove All Stored Images</label>
|
||||
</channel-type>
|
||||
</thing:thing-descriptions>
|
@ -1,44 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="mercedesme"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
<channel-type id="interior-front-channel">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Interior Light Front</label>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="interior-rear-channel">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Interior Light Rear</label>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="reading-left-channel">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Reading Light Left</label>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="reading-right-channel">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Reading Light Right</label>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="light-switch-channel">
|
||||
<item-type>Number</item-type>
|
||||
<label>Main Light Rotary</label>
|
||||
<state readOnly="true">
|
||||
<options>
|
||||
<option value="0">Auto</option>
|
||||
<option value="1">Headlight</option>
|
||||
<option value="2">Sidelight Left</option>
|
||||
<option value="3">Sidelight Right</option>
|
||||
<option value="4">Parking Light</option>
|
||||
</options>
|
||||
</state>
|
||||
</channel-type>
|
||||
<channel-type id="last-lights-update-channel">
|
||||
<item-type>DateTime</item-type>
|
||||
<label>Last Light Update</label>
|
||||
<state pattern="%1$tA, %1$td.%1$tm. %1$tH:%1$tM" readOnly="true"/>
|
||||
</channel-type>
|
||||
</thing:thing-descriptions>
|
@ -1,18 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="mercedesme"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
<channel-group-type id="light-values">
|
||||
<label>Light Status</label>
|
||||
<description>Light Status of interior lights and main light switch</description>
|
||||
<channels>
|
||||
<channel id="interior-front" typeId="interior-front-channel"/>
|
||||
<channel id="interior-rear" typeId="interior-rear-channel"/>
|
||||
<channel id="light-switch" typeId="light-switch-channel"/>
|
||||
<channel id="reading-left" typeId="reading-left-channel"/>
|
||||
<channel id="reading-right" typeId="reading-right-channel"/>
|
||||
<channel id="last-update" typeId="last-lights-update-channel"/>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
</thing:thing-descriptions>
|
@ -3,31 +3,34 @@
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
<channel-type id="doors-lock-channel">
|
||||
<item-type>Number</item-type>
|
||||
<label>Door Lock Status</label>
|
||||
<state readOnly="true">
|
||||
<options>
|
||||
<option value="0">Unlocked</option>
|
||||
<option value="1">Locked Internal</option>
|
||||
<option value="2">Locked External</option>
|
||||
<option value="3">Unlocked Selective</option>
|
||||
</options>
|
||||
</state>
|
||||
<channel-type id="front-left-lock">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Door Lock Front Left</label>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="deck-lid-lock-channel">
|
||||
<channel-type id="front-right-lock">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Door Lock Front Right</label>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="rear-left-lock">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Door Lock Rear Left</label>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="rear-right-lock">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Door Lock Rear Right</label>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="deck-lid-lock">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Deck Lid Lock</label>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="flap-lock-channel">
|
||||
<channel-type id="gas-flap-lock">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Flap Lock</label>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="last-lock-update-channel">
|
||||
<item-type>DateTime</item-type>
|
||||
<label>Last Lock Update</label>
|
||||
<state pattern="%1$tA, %1$td.%1$tm. %1$tH:%1$tM" readOnly="true"/>
|
||||
</channel-type>
|
||||
</thing:thing-descriptions>
|
||||
|
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="mercedesme"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
<channel-group-type id="lock-ev-values">
|
||||
<label>Lock Status</label>
|
||||
<description>Door Lock Status</description>
|
||||
<channels>
|
||||
<channel id="front-left" typeId="front-left-lock"/>
|
||||
<channel id="front-right" typeId="front-right-lock"/>
|
||||
<channel id="rear-left" typeId="rear-left-lock"/>
|
||||
<channel id="rear-right" typeId="rear-right-lock"/>
|
||||
<channel id="deck-lid" typeId="deck-lid-lock"/>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
</thing:thing-descriptions>
|
@ -5,12 +5,14 @@
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
<channel-group-type id="lock-values">
|
||||
<label>Lock Status</label>
|
||||
<description>Vehicle Lock Status</description>
|
||||
<description>Door Lock Status</description>
|
||||
<channels>
|
||||
<channel id="doors" typeId="doors-lock-channel"/>
|
||||
<channel id="deck-lid" typeId="deck-lid-lock-channel"/>
|
||||
<channel id="flap" typeId="flap-lock-channel"/>
|
||||
<channel id="last-update" typeId="last-lock-update-channel"/>
|
||||
<channel id="front-left" typeId="front-left-lock"/>
|
||||
<channel id="front-right" typeId="front-right-lock"/>
|
||||
<channel id="rear-left" typeId="rear-left-lock"/>
|
||||
<channel id="rear-right" typeId="rear-right-lock"/>
|
||||
<channel id="deck-lid" typeId="deck-lid-lock"/>
|
||||
<channel id="gas-flap" typeId="gas-flap-lock"/>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
</thing:thing-descriptions>
|
||||
|
@ -3,12 +3,13 @@
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
<channel-group-type id="location-values">
|
||||
<channel-group-type id="position-values">
|
||||
<label>Vehicle Location</label>
|
||||
<description>Heading of vehicle</description>
|
||||
<channels>
|
||||
<channel id="heading" typeId="heading-channel"/>
|
||||
<channel id="last-update" typeId="last-location-update-channel"/>
|
||||
<channel id="heading" typeId="heading"/>
|
||||
<channel id="gps" typeId="gps"/>
|
||||
<channel id="signal" typeId="signal"/>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
</thing:thing-descriptions>
|
@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="mercedesme"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
<channel-type id="heading">
|
||||
<item-type>Number:Angle</item-type>
|
||||
<label>Position Heading Angle</label>
|
||||
<state pattern="%d %unit%" readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="gps">
|
||||
<item-type>Location</item-type>
|
||||
<label>Position GPS</label>
|
||||
</channel-type>
|
||||
<channel-type id="signal">
|
||||
<item-type>Number</item-type>
|
||||
<label>Position Signal</label>
|
||||
<state>
|
||||
<options>
|
||||
<option value="0">Position Lights</option>
|
||||
<option value="1">Position Horn</option>
|
||||
</options>
|
||||
</state>
|
||||
<command>
|
||||
<options>
|
||||
<option value="0">Position Lights</option>
|
||||
<option value="1">Position Horn</option>
|
||||
</options>
|
||||
</command>
|
||||
</channel-type>
|
||||
</thing:thing-descriptions>
|
@ -3,74 +3,74 @@
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
<channel-type id="mileage-channel">
|
||||
<channel-type id="mileage">
|
||||
<item-type>Number:Length</item-type>
|
||||
<label>Mileage</label>
|
||||
<state pattern="%d %unit%" readOnly="true"/>
|
||||
<state pattern="%d km" readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="range-electric-channel">
|
||||
<channel-type id="range-electric">
|
||||
<item-type>Number:Length</item-type>
|
||||
<label>Electric Range</label>
|
||||
<state pattern="%d %unit%" readOnly="true"/>
|
||||
<state pattern="%d km" readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="radius-electric-channel">
|
||||
<channel-type id="radius-electric">
|
||||
<item-type>Number:Length</item-type>
|
||||
<label>Electric Radius</label>
|
||||
<state pattern="%d %unit%" readOnly="true"/>
|
||||
<state pattern="%d km" readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="soc-channel">
|
||||
<channel-type id="home-distance">
|
||||
<item-type>Number:Length</item-type>
|
||||
<label>Distance to Home</label>
|
||||
<state pattern="%.3f km" readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="soc">
|
||||
<item-type>Number:Dimensionless</item-type>
|
||||
<label>Battery Charge Level</label>
|
||||
<state pattern="%d %unit%" readOnly="true"/>
|
||||
<state pattern="%d %" readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="charged-channel">
|
||||
<channel-type id="charged">
|
||||
<item-type>Number:Energy</item-type>
|
||||
<label>Charged Battery Energy</label>
|
||||
<state pattern="%.2f %unit%" readOnly="true"/>
|
||||
<state pattern="%.2f kWh" readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="uncharged-channel">
|
||||
<channel-type id="uncharged">
|
||||
<item-type>Number:Energy</item-type>
|
||||
<label>Uncharged Battery Energy</label>
|
||||
<state pattern="%.2f %unit%" readOnly="true"/>
|
||||
<state pattern="%.2f kWh" readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="range-fuel-channel">
|
||||
<channel-type id="range-fuel">
|
||||
<item-type>Number:Length</item-type>
|
||||
<label>Fuel Range</label>
|
||||
<state pattern="%d %unit%" readOnly="true"/>
|
||||
<state pattern="%d km" readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="radius-fuel-channel">
|
||||
<channel-type id="radius-fuel">
|
||||
<item-type>Number:Length</item-type>
|
||||
<label>Fuel Radius</label>
|
||||
<state pattern="%d %unit%" readOnly="true"/>
|
||||
<state pattern="%d km" readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="fuel-level-channel">
|
||||
<channel-type id="fuel-level">
|
||||
<item-type>Number:Dimensionless</item-type>
|
||||
<label>Fuel Level</label>
|
||||
<state pattern="%d %unit%" readOnly="true"/>
|
||||
<state pattern="%d %%" readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="fuel-remain-channel">
|
||||
<channel-type id="fuel-remain">
|
||||
<item-type>Number:Volume</item-type>
|
||||
<label>Remaining Fuel</label>
|
||||
<state pattern="%.2f %unit%" readOnly="true"/>
|
||||
<state pattern="%.2f l" readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="fuel-open-channel">
|
||||
<channel-type id="fuel-open">
|
||||
<item-type>Number:Volume</item-type>
|
||||
<label>Open Fuel Capacity</label>
|
||||
<state pattern="%.2f %unit%" readOnly="true"/>
|
||||
<state pattern="%.2f l" readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="range-hybrid-channel">
|
||||
<channel-type id="range-hybrid">
|
||||
<item-type>Number:Length</item-type>
|
||||
<label>Hybrid Range</label>
|
||||
<state pattern="%d %unit%" readOnly="true"/>
|
||||
<state pattern="%d km" readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="radius-hybrid-channel">
|
||||
<channel-type id="radius-hybrid">
|
||||
<item-type>Number:Length</item-type>
|
||||
<label>Hybrid Radius</label>
|
||||
<state pattern="%d %unit%" readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="last-range-update-channel">
|
||||
<item-type>DateTime</item-type>
|
||||
<label>Last Range Update</label>
|
||||
<state pattern="%1$tA, %1$td.%1$tm. %1$tH:%1$tM" readOnly="true"/>
|
||||
<state pattern="%d km" readOnly="true"/>
|
||||
</channel-type>
|
||||
</thing:thing-descriptions>
|
||||
|
@ -7,13 +7,13 @@
|
||||
<label>Range and Fuel Data</label>
|
||||
<description>Provides Mileage, remaining range and fuel level values</description>
|
||||
<channels>
|
||||
<channel id="mileage" typeId="mileage-channel"/>
|
||||
<channel id="range-fuel" typeId="range-fuel-channel"/>
|
||||
<channel id="radius-fuel" typeId="radius-fuel-channel"/>
|
||||
<channel id="fuel-level" typeId="fuel-level-channel"/>
|
||||
<channel id="fuel-remain" typeId="fuel-remain-channel"/>
|
||||
<channel id="fuel-open" typeId="fuel-open-channel"/>
|
||||
<channel id="last-update" typeId="last-range-update-channel"/>
|
||||
<channel id="mileage" typeId="mileage"/>
|
||||
<channel id="range-fuel" typeId="range-fuel"/>
|
||||
<channel id="radius-fuel" typeId="radius-fuel"/>
|
||||
<channel id="home-distance" typeId="home-distance"/>
|
||||
<channel id="fuel-level" typeId="fuel-level"/>
|
||||
<channel id="fuel-remain" typeId="fuel-remain"/>
|
||||
<channel id="fuel-open" typeId="fuel-open"/>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
</thing:thing-descriptions>
|
||||
|
@ -4,16 +4,16 @@
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
<channel-group-type id="range-ev-values">
|
||||
<label>Range and Charge Data</label>
|
||||
<label>Range and Battery Data</label>
|
||||
<description>Provides Mileage, remaining range and charge level values</description>
|
||||
<channels>
|
||||
<channel id="mileage" typeId="mileage-channel"/>
|
||||
<channel id="range-electric" typeId="range-electric-channel"/>
|
||||
<channel id="radius-electric" typeId="radius-electric-channel"/>
|
||||
<channel id="soc" typeId="soc-channel"/>
|
||||
<channel id="charged" typeId="charged-channel"/>
|
||||
<channel id="uncharged" typeId="uncharged-channel"/>
|
||||
<channel id="last-update" typeId="last-range-update-channel"/>
|
||||
<channel id="mileage" typeId="mileage"/>
|
||||
<channel id="range-electric" typeId="range-electric"/>
|
||||
<channel id="radius-electric" typeId="radius-electric"/>
|
||||
<channel id="home-distance" typeId="home-distance"/>
|
||||
<channel id="soc" typeId="soc"/>
|
||||
<channel id="charged" typeId="charged"/>
|
||||
<channel id="uncharged" typeId="uncharged"/>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
</thing:thing-descriptions>
|
||||
|
@ -4,23 +4,23 @@
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
<channel-group-type id="range-hybrid-values">
|
||||
<label>Range, Charge / Fuel Data</label>
|
||||
<label>Range, Battery and Fuel Data</label>
|
||||
<description>Provides mileage, remaining fuel and range data for hybrid vehicles</description>
|
||||
<channels>
|
||||
<channel id="mileage" typeId="mileage-channel"/>
|
||||
<channel id="range-electric" typeId="range-electric-channel"/>
|
||||
<channel id="radius-electric" typeId="radius-electric-channel"/>
|
||||
<channel id="soc" typeId="soc-channel"/>
|
||||
<channel id="charged" typeId="charged-channel"/>
|
||||
<channel id="uncharged" typeId="uncharged-channel"/>
|
||||
<channel id="range-fuel" typeId="range-fuel-channel"/>
|
||||
<channel id="radius-fuel" typeId="radius-fuel-channel"/>
|
||||
<channel id="fuel-level" typeId="fuel-level-channel"/>
|
||||
<channel id="fuel-remain" typeId="fuel-remain-channel"/>
|
||||
<channel id="fuel-open" typeId="fuel-open-channel"/>
|
||||
<channel id="range-hybrid" typeId="range-hybrid-channel"/>
|
||||
<channel id="radius-hybrid" typeId="radius-fuel-channel"/>
|
||||
<channel id="last-update" typeId="last-range-update-channel"/>
|
||||
<channel id="mileage" typeId="mileage"/>
|
||||
<channel id="range-electric" typeId="range-electric"/>
|
||||
<channel id="radius-electric" typeId="radius-electric"/>
|
||||
<channel id="home-distance" typeId="home-distance"/>
|
||||
<channel id="soc" typeId="soc"/>
|
||||
<channel id="charged" typeId="charged"/>
|
||||
<channel id="uncharged" typeId="uncharged"/>
|
||||
<channel id="range-fuel" typeId="range-fuel"/>
|
||||
<channel id="radius-fuel" typeId="radius-fuel"/>
|
||||
<channel id="fuel-level" typeId="fuel-level"/>
|
||||
<channel id="fuel-remain" typeId="fuel-remain"/>
|
||||
<channel id="fuel-open" typeId="fuel-open"/>
|
||||
<channel id="range-hybrid" typeId="range-hybrid"/>
|
||||
<channel id="radius-hybrid" typeId="radius-fuel"/>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
</thing:thing-descriptions>
|
||||
|
@ -0,0 +1,54 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="mercedesme"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
<channel-type id="starter-battery">
|
||||
<item-type>Number</item-type>
|
||||
<label>Starter Battery Status</label>
|
||||
<state readOnly="true">
|
||||
<options>
|
||||
<option value="0">Green</option>
|
||||
<option value="1">Yellow</option>
|
||||
<option value="2">Red</option>
|
||||
</options>
|
||||
</state>
|
||||
</channel-type>
|
||||
<channel-type id="brake-fluid">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Brake Fluid</label>
|
||||
<state readOnly="true"></state>
|
||||
</channel-type>
|
||||
<channel-type id="brake-lining-wear">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Brake Lining Wear</label>
|
||||
<state readOnly="true"></state>
|
||||
</channel-type>
|
||||
<channel-type id="wash-water">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Wash Water Low</label>
|
||||
<state readOnly="true"></state>
|
||||
</channel-type>
|
||||
<channel-type id="coolant-fluid">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Coolant Fluid Low</label>
|
||||
<state readOnly="true"></state>
|
||||
</channel-type>
|
||||
<channel-type id="engine">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Engine Warning</label>
|
||||
<state readOnly="true"></state>
|
||||
</channel-type>
|
||||
<channel-type id="tires-rdk">
|
||||
<item-type>Number</item-type>
|
||||
<label>Tire Pressure Warnings</label>
|
||||
<state readOnly="true">
|
||||
</state>
|
||||
</channel-type>
|
||||
<channel-type id="service-days">
|
||||
<item-type>Number</item-type>
|
||||
<label>Service in Days</label>
|
||||
<state readOnly="true">
|
||||
</state>
|
||||
</channel-type>
|
||||
</thing:thing-descriptions>
|
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="mercedesme"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
<channel-group-type id="service-ev-values">
|
||||
<label>Service and Warnings</label>
|
||||
<channels>
|
||||
<channel id="starter-battery" typeId="starter-battery"/>
|
||||
<channel id="brake-fluid" typeId="brake-fluid"/>
|
||||
<channel id="brake-lining-wear" typeId="brake-lining-wear"/>
|
||||
<channel id="wash-water" typeId="wash-water"/>
|
||||
<channel id="tires-rdk" typeId="tires-rdk"/>
|
||||
<channel id="service-days" typeId="service-days"/>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
</thing:thing-descriptions>
|
@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="mercedesme"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
<channel-group-type id="service-values">
|
||||
<label>Warnings</label>
|
||||
<description>Current active warnings</description>
|
||||
<channels>
|
||||
<channel id="starter-battery" typeId="starter-battery"/>
|
||||
<channel id="brake-fluid" typeId="brake-fluid"/>
|
||||
<channel id="brake-lining-wear" typeId="brake-lining-wear"/>
|
||||
<channel id="wash-water" typeId="wash-water"/>
|
||||
<channel id="tires-rdk" typeId="tires-rdk"/>
|
||||
<channel id="coolant-fluid" typeId="coolant-fluid"/>
|
||||
<channel id="engine" typeId="engine"/>
|
||||
<channel id="service-days" typeId="service-days"/>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
</thing:thing-descriptions>
|
@ -13,13 +13,18 @@
|
||||
<description>Battery Electric Vehicle</description>
|
||||
|
||||
<channel-groups>
|
||||
<channel-group id="range" typeId="range-ev-values"/>
|
||||
<channel-group id="vehicle" typeId="vehicle-values"/>
|
||||
<channel-group id="doors" typeId="door-values"/>
|
||||
<channel-group id="lock" typeId="lock-ev-values"/>
|
||||
<channel-group id="windows" typeId="window-values"/>
|
||||
<channel-group id="lights" typeId="light-values"/>
|
||||
<channel-group id="lock" typeId="lock-values"/>
|
||||
<channel-group id="location" typeId="location-values"/>
|
||||
<channel-group id="image" typeId="image-values"/>
|
||||
<channel-group id="hvac" typeId="hvac-values"/>
|
||||
<channel-group id="service" typeId="service-ev-values"/>
|
||||
<channel-group id="range" typeId="range-ev-values"/>
|
||||
<channel-group id="charge" typeId="charge-values"/>
|
||||
<channel-group id="trip" typeId="trip-ev-values"/>
|
||||
<channel-group id="position" typeId="position-values"/>
|
||||
<channel-group id="tires" typeId="tires-values"/>
|
||||
<channel-group id="command" typeId="command-values"/>
|
||||
</channel-groups>
|
||||
|
||||
<config-description-ref uri="thing-type:mercedesme:bev"/>
|
||||
|
@ -13,13 +13,17 @@
|
||||
<description>Conventional Fuel Vehicle</description>
|
||||
|
||||
<channel-groups>
|
||||
<channel-group id="range" typeId="range-conv-values"/>
|
||||
<channel-group id="vehicle" typeId="vehicle-values"/>
|
||||
<channel-group id="doors" typeId="door-values"/>
|
||||
<channel-group id="windows" typeId="window-values"/>
|
||||
<channel-group id="lights" typeId="light-values"/>
|
||||
<channel-group id="lock" typeId="lock-values"/>
|
||||
<channel-group id="location" typeId="location-values"/>
|
||||
<channel-group id="image" typeId="image-values"/>
|
||||
<channel-group id="windows" typeId="window-values"/>
|
||||
<channel-group id="hvac" typeId="hvac-values"/>
|
||||
<channel-group id="service" typeId="service-values"/>
|
||||
<channel-group id="range" typeId="range-conv-values"/>
|
||||
<channel-group id="trip" typeId="trip-values"/>
|
||||
<channel-group id="position" typeId="position-values"/>
|
||||
<channel-group id="tires" typeId="tires-values"/>
|
||||
<channel-group id="command" typeId="command-values"/>
|
||||
</channel-groups>
|
||||
|
||||
<config-description-ref uri="thing-type:mercedesme:conv"/>
|
||||
|
@ -13,13 +13,18 @@
|
||||
<description>Conventional Fuel Vehicle with supporting Electric Engine</description>
|
||||
|
||||
<channel-groups>
|
||||
<channel-group id="range" typeId="range-hybrid-values"/>
|
||||
<channel-group id="vehicle" typeId="vehicle-values"/>
|
||||
<channel-group id="doors" typeId="door-values"/>
|
||||
<channel-group id="windows" typeId="window-values"/>
|
||||
<channel-group id="lights" typeId="light-values"/>
|
||||
<channel-group id="lock" typeId="lock-values"/>
|
||||
<channel-group id="location" typeId="location-values"/>
|
||||
<channel-group id="image" typeId="image-values"/>
|
||||
<channel-group id="windows" typeId="window-values"/>
|
||||
<channel-group id="hvac" typeId="hvac-values"/>
|
||||
<channel-group id="service" typeId="service-values"/>
|
||||
<channel-group id="range" typeId="range-hybrid-values"/>
|
||||
<channel-group id="charge" typeId="charge-values"/>
|
||||
<channel-group id="trip" typeId="trip-hybrid-values"/>
|
||||
<channel-group id="position" typeId="position-values"/>
|
||||
<channel-group id="tires" typeId="tires-values"/>
|
||||
<channel-group id="command" typeId="command-values"/>
|
||||
</channel-groups>
|
||||
|
||||
<config-description-ref uri="thing-type:mercedesme:hybrid"/>
|
||||
|
@ -0,0 +1,88 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="mercedesme"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
<channel-type id="pressure-front-right">
|
||||
<item-type>Number:Pressure</item-type>
|
||||
<label>Tire Pressure Front Right</label>
|
||||
<state pattern="%.1f bar" readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="pressure-rear-right">
|
||||
<item-type>Number:Pressure</item-type>
|
||||
<label>Tire Pressure Rear Right</label>
|
||||
<state pattern="%.1f bar" readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="pressure-front-left">
|
||||
<item-type>Number:Pressure</item-type>
|
||||
<label>Tire Pressure Front Left</label>
|
||||
<state pattern="%.1f bar" readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="pressure-rear-left">
|
||||
<item-type>Number:Pressure</item-type>
|
||||
<label>Tire Pressure Rear Left</label>
|
||||
<state pattern="%.1f bar" readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="sensor-available">
|
||||
<item-type>Number</item-type>
|
||||
<label>Tire Sensor Available</label>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="marker-front-right">
|
||||
<item-type>Number</item-type>
|
||||
<label>Tire Warning Front Right</label>
|
||||
<state readOnly="true">
|
||||
<options>
|
||||
<option value="0">No warning</option>
|
||||
<option value="1">Soft warning</option>
|
||||
<option value="2">Low warning</option>
|
||||
<option value="3">Deflation</option>
|
||||
<option value="4">Unknown warning</option>
|
||||
</options>
|
||||
</state>
|
||||
</channel-type>
|
||||
<channel-type id="marker-rear-right">
|
||||
<item-type>Number</item-type>
|
||||
<label>Tire Warning Rear Right</label>
|
||||
<state readOnly="true">
|
||||
<options>
|
||||
<option value="0">No warning</option>
|
||||
<option value="1">Soft warning</option>
|
||||
<option value="2">Low warning</option>
|
||||
<option value="3">Deflation</option>
|
||||
<option value="4">Unknown warning</option>
|
||||
</options>
|
||||
</state>
|
||||
</channel-type>
|
||||
<channel-type id="marker-front-left">
|
||||
<item-type>Number</item-type>
|
||||
<label>Tire Warning Front Left</label>
|
||||
<state readOnly="true">
|
||||
<options>
|
||||
<option value="0">No warning</option>
|
||||
<option value="1">Soft warning</option>
|
||||
<option value="2">Low warning</option>
|
||||
<option value="3">Deflation</option>
|
||||
<option value="4">Unknown warning</option>
|
||||
</options>
|
||||
</state>
|
||||
</channel-type>
|
||||
<channel-type id="marker-rear-left">
|
||||
<item-type>Number</item-type>
|
||||
<label>Tire Warning Rear Left</label>
|
||||
<state readOnly="true">
|
||||
<options>
|
||||
<option value="0">No warning</option>
|
||||
<option value="1">Soft warning</option>
|
||||
<option value="2">Low warning</option>
|
||||
<option value="3">Deflation</option>
|
||||
<option value="4">Unknown warning</option>
|
||||
</options>
|
||||
</state>
|
||||
</channel-type>
|
||||
<channel-type id="last-update">
|
||||
<item-type>DateTime</item-type>
|
||||
<label>Tire Update Time</label>
|
||||
<state pattern="%1$tA, %1$td.%1$tm. %1$tH:%1$tM" readOnly="true"/>
|
||||
</channel-type>
|
||||
</thing:thing-descriptions>
|
@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="mercedesme"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
<channel-group-type id="tires-values">
|
||||
<label>Tire Status</label>
|
||||
<description>Tire Pressure Values</description>
|
||||
<channels>
|
||||
<channel id="pressure-front-right" typeId="pressure-front-right"/>
|
||||
<channel id="pressure-rear-right" typeId="pressure-rear-right"/>
|
||||
<channel id="pressure-front-left" typeId="pressure-front-left"/>
|
||||
<channel id="pressure-rear-left" typeId="pressure-rear-left"/>
|
||||
<channel id="sensor-available" typeId="sensor-available"/>
|
||||
<channel id="marker-front-right" typeId="marker-front-right"/>
|
||||
<channel id="marker-rear-right" typeId="marker-rear-right"/>
|
||||
<channel id="marker-front-left" typeId="marker-front-left"/>
|
||||
<channel id="marker-rear-left" typeId="marker-rear-left"/>
|
||||
<channel id="last-update" typeId="last-update"/>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
</thing:thing-descriptions>
|
@ -0,0 +1,75 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="mercedesme"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
<channel-type id="distance">
|
||||
<item-type>Number:Length</item-type>
|
||||
<label>Trip Distance</label>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="driven-time">
|
||||
<item-type>String</item-type>
|
||||
<label>Trip String Time</label>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="avg-speed">
|
||||
<item-type>Number:Speed</item-type>
|
||||
<label>Trip Average Speed</label>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="consumption-ev">
|
||||
<item-type>Number</item-type>
|
||||
<label>Trip Avg Cons EV</label>
|
||||
<description>Last Trip Average Consumption Electric</description>
|
||||
<state pattern="%.1f" readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="consumption-conv">
|
||||
<item-type>Number</item-type>
|
||||
<label>Trip Avg Cons Fuel</label>
|
||||
<description>Last Trip Average Consumption Fuel</description>
|
||||
<state pattern="%.1f" readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="distance-reset">
|
||||
<item-type>Number:Length</item-type>
|
||||
<label>Rst Distance</label>
|
||||
<description>Distance since last Reset</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="driven-time-reset">
|
||||
<item-type>String</item-type>
|
||||
<label>Rst Driving Time</label>
|
||||
<description>Driving time since last Reset</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="avg-speed-reset">
|
||||
<item-type>Number:Speed</item-type>
|
||||
<label>Rst Average Speed</label>
|
||||
<description>Average speed since last Reset</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="consumption-ev-reset">
|
||||
<item-type>Number</item-type>
|
||||
<label>Avg Cons Rst EV</label>
|
||||
<description>Average consumption since last reset electric</description>
|
||||
<state pattern="%.1f" readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="consumption-conv-reset">
|
||||
<item-type>Number</item-type>
|
||||
<label>Avg Cons Rst Fuel</label>
|
||||
<description>Average consumption since last reset fuel</description>
|
||||
<state pattern="%.1f" readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="consumption-ev-unit">
|
||||
<item-type>String</item-type>
|
||||
<label>Avg Cons Unit EV</label>
|
||||
<description>Average consumption unit electric</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="consumption-conv-unit">
|
||||
<item-type>String</item-type>
|
||||
<label>Avg Cons Unit Fuel</label>
|
||||
<description>Average consumption unit fuel</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
</thing:thing-descriptions>
|