Last active
January 15, 2019 04:33
-
-
Save maxlapshin/1c803f05dd90c2ae98655988208c990a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env escript | |
%% | |
%% | |
-mode(compile). | |
main([IP]) -> | |
{ok, Socket} = gen_tcp:connect(IP, 1560, [binary, {active,false}]), | |
loop(Socket); | |
main([IP, "set_speed", Speed]) -> | |
{ok, Socket} = gen_tcp:connect(IP, 1560, [binary, {active,false}]), | |
call(Socket, set_speed, list_to_integer(Speed)), | |
timer:sleep(2000), | |
Stat = call(Socket, status), | |
io:format("~s\n~160p\n", [maps:get(msg,Stat,""),Stat]), | |
ok; | |
main([IP, "set_zone_speed", Zone_, Speed_, Level_]) -> | |
{ok, Socket} = gen_tcp:connect(IP, 1560, [binary, {active,false}]), | |
Zone = list_to_integer(Zone_), | |
Speed = case Speed_ of | |
"-" -> undefined; | |
_ -> list_to_integer(Speed_) | |
end, | |
Level = case Level_ of | |
"-" -> undefined; | |
_ -> list_to_integer(Level_) | |
end, | |
call(Socket, set_zone_speed, {Zone, Speed, Level}), | |
timer:sleep(2000), | |
io:format("Zone: ~160p\n", [call(Socket, zone_level, Zone)]), | |
Stat = call(Socket, status), | |
io:format("~s\n~160p\n", [maps:get(msg,Stat,""),Stat]), | |
ok; | |
main([IP, "set_power", Value]) -> | |
{ok, Socket} = gen_tcp:connect(IP, 1560, [binary, {active,false}]), | |
call(Socket, set_power, Value == "on"), | |
timer:sleep(1000), | |
Stat = call(Socket, status), | |
io:format("~s\n~160p\n", [maps:get(msg,Stat,""),Stat]), | |
ok; | |
main([IP, "set_options", Key, Value_]) when Key == "mode"; Key == "humidifier"; Key == "comfort"; Key == "restart" -> | |
{ok, Socket} = gen_tcp:connect(IP, 1560, [binary, {active,false}]), | |
Value = case Value_ of | |
"on" -> true; | |
"off" -> false; | |
"warm" -> warm; | |
"cool" -> cool; | |
"auto" -> auto; | |
"disabled" -> disabled | |
end, | |
Arg = #{list_to_atom(Key) => Value}, | |
call(Socket, set_options, Arg), | |
timer:sleep(1000), | |
Stat = call(Socket, status), | |
io:format("~s\n~160p\n", [maps:get(msg,Stat,""),Stat]), | |
ok. | |
loop(Socket) -> | |
HS = call(Socket, handshake), | |
io:format("~160p\n", [HS]), | |
Stat = call(Socket, status), | |
io:format("~s\n~160p\n", [maps:get(msg,Stat,""),Stat]), | |
io:format("Zone1: ~160p\n", [call(Socket, zone_level, 1)]), | |
io:format("Zone2: ~160p\n", [call(Socket, zone_level, 2)]), | |
io:format("Zone3: ~160p\n", [call(Socket, zone_level, 3)]), | |
io:format("Zone4: ~160p\n", [call(Socket, zone_level, 4)]), | |
io:format("Sensors: ~160p\n", [call(Socket, sensors)]), | |
ok. | |
call(Socket, Command) -> | |
call(Socket, Command, undefined). | |
call(Socket, Command, Argument) -> | |
Code = case Command of | |
handshake -> "VPr07"; | |
status -> "VSt07"; | |
zone_level -> "VZL0"++integer_to_list(Argument); | |
sensors -> "VSens"; | |
set_temperature -> "VWTmp"; | |
set_power -> "VWPwr"; | |
set_humidity -> "VWHum"; | |
set_speed -> "VWSpd"; | |
set_zone_speed -> "VWZon"; | |
set_options -> "VWFtr" | |
end, | |
Postfix = case Command of | |
set_power -> "_" ++ integer_to_list(case Argument of true -> 11; false -> 10 end, 16); | |
set_temperature -> "_"++integer_to_list(Argument,16); | |
set_humidity -> "_" ++ integer_to_list(Argument,16); | |
set_speed -> "_"++ integer_to_list(Argument,16); | |
set_zone_speed -> | |
{ZoneNumber,TargetSpeedV,ZoneLevelV} = Argument, | |
ZoneLevel = case ZoneLevelV of | |
undefined -> 255; | |
_ -> ZoneLevelV | |
end, | |
TargetSpeed = case TargetSpeedV of | |
undefined -> 15; | |
_ -> TargetSpeedV | |
end, | |
"_" ++ integer_to_list(TargetSpeed,16)++"_"++integer_to_list(ZoneNumber,16)++"_"++integer_to_list(ZoneLevel,16); | |
set_options -> | |
ModeSet = case maps:get(mode,Argument,undefined) of | |
undefined -> 0; | |
warm -> 1; | |
cool -> 2; | |
auto -> 3; | |
disabled -> 4 | |
end, | |
HumidSet = case maps:get(humidifier,Argument,undefined) of | |
undefined -> 0; | |
true -> 1; | |
false -> 2 | |
end, | |
Comfort = case maps:get(comfort,Argument,undefined) of | |
undefined -> 0; | |
true -> 1; | |
false -> 2 | |
end, | |
Restart = case maps:get(restart,Argument,undefined) of | |
undefined -> 0; | |
true -> 1; | |
false -> 2 | |
end, | |
<<B1:8,B2:8>> = <<0:7, Restart:2, Comfort:2, HumidSet:2, ModeSet:3>>, | |
<<B:16>> = <<B1:8,B2:8>>, | |
"_"++integer_to_list(B,16); | |
_ -> | |
"" | |
end, | |
ok = gen_tcp:send(Socket, [Code,"_70B6",Postfix]), | |
{ok, Bin1} = gen_tcp:recv(Socket, 0), | |
Reply = parse(Bin1), | |
Reply. | |
parse(<<"OK_",Command/binary>>) -> | |
Parts = binary:split(Command, <<"_">>, [global]), | |
{ok, Parts}; | |
parse(<<Code:5/binary, "_", Command/binary>>) -> | |
Parts = [if | |
size(Part) == 3 orelse size(Part) == 4 -> <<(binary_to_integer(Part,16)):16/little>>; | |
true -> Part | |
end || Part <- binary:split(Command, <<"_">>, [global])], | |
parse2(Code, Parts). | |
parse2(<<"VSens">>, [<<>>, TInf, HInf, TRoom, HRoom, TOut, HOut, THF, <<Pwr1,Pwr2>>]) -> | |
% D = fun(<<7,16#FB>>) -> undefined; | |
% () | |
#{ | |
temp_vent => TInf, | |
humidity_vent => HInf, | |
temp_room => TRoom, | |
humidity_room => HRoom, | |
temp_out => TOut, | |
humidity_out => HOut, | |
temp_water => THF, | |
power => binary:decode_unsigned(<<Pwr2,Pwr1>>) | |
}; | |
parse2(<<"VPr07">>, [<<TempMin, TempMax>>, <<SpeedMin, SpeedMax>>, <<HumidMin,HumidMax>>, | |
Misc, Protocol, <<TPD1,TPD2>>, Controller| _Parts]) -> | |
<<_:3, VavZones:5, IsAuto:1, HasCooler:1, HasHumid:1, HasCascH:1, HasCascT:1, ShowHumid:1, | |
EnabledVavReg:1, EnabledVav:1>> = Misc, | |
#{temp => [TempMin, TempMax], | |
speed => [SpeedMin, SpeedMax], | |
humidity => [HumidMin,HumidMax], | |
vav_zone_count => VavZones, | |
vav_enabled => EnabledVav == 1, | |
vav_pressure_enabled => EnabledVavReg == 1, | |
show_humidity => ShowHumid == 1, | |
has_cascade_t => HasCascT == 1, | |
has_cascade_h => HasCascH == 1, | |
has_humidifier => HasHumid == 1, | |
has_cooler => HasCooler == 1, | |
has_auto_cooling => IsAuto == 1, | |
protocol => Protocol, | |
tpd => {TPD2,TPD1}, controller => binary:decode_unsigned(Controller)}; | |
parse2(<<"VSt07">>, [<<S0,S1>>, <<M0,M1>>, <<TempCurrent,TempTarget>>, | |
<<Humidity, HumidityTarget>>, <<SpeedTarget:4, Speed:4, SpeedFact:8>>, <<MS0,MS1>>, | |
<<Min,Hour>>, <<Day,Month>>, <<Dow, Year>>, Msg|_]) -> | |
<<PowerBlocked:1, ScenarioBlocked:1, HumidAuto:1, ComfortOn:1, RestartOn:1, | |
SpeedIsDown:1, HumidOn:1, ModeSet:3, ChangeFilter:1, AutoOff:1, Overheat:1, | |
HasError:1, HasWarning:1, PowerOn:1>> = <<S1,S0>>, | |
State = #{ | |
on => PowerOn == 1, | |
has_warning => HasWarning == 1, | |
has_error => HasError == 1, | |
overheat => Overheat == 1, | |
auto_off => AutoOff == 1, | |
change_filter => ChangeFilter == 1, | |
mode_set => case ModeSet of | |
1 -> warm; | |
2 -> cool; | |
3 -> auto; | |
4 -> disabled | |
end, | |
humidifier_enabled => HumidOn == 1, | |
speed_is_down => SpeedIsDown == 1, | |
restart_on => RestartOn == 1, | |
comfort_on => ComfortOn == 1, | |
auto_humidifier => HumidAuto == 1, | |
scenario_blocked => ScenarioBlocked == 1, | |
power_blocked => PowerBlocked == 1 | |
}, | |
<<NumIcoHF:3, WhoActivateScen:3, | |
NumActiveScen:4, WorkModeCode:3, ScenAllow:1, UnitStateCode:2>> = <<M1,M0>>, | |
Mode = #{ | |
unit_state => case UnitStateCode of | |
0 -> off; | |
1 -> on; | |
2 -> turning_on; | |
3 -> turning_off | |
end, | |
scenario_allowed => ScenAllow == 1, | |
current_mode => case WorkModeCode of | |
0 -> heating; | |
1 -> cooling; | |
2 -> auto_heating; | |
3 -> auto_cooling; | |
4 -> passthrough; | |
5 -> off | |
end, | |
active_scenario => NumActiveScen, | |
scenario_activator => case WhoActivateScen of | |
0 -> disabled; | |
1 -> timer1; | |
2 -> timer2; | |
3 -> manual; | |
4 -> later | |
end, | |
current_icon => NumIcoHF | |
}, | |
<<FilterDust:8, ColorInd:2, ColorMsg:2, TempMin:4>> = <<MS1,MS0>>, | |
Misc = #{ | |
minimal_temp => TempMin, | |
message_color => case ColorMsg of | |
0 -> normal; | |
1 -> warning; | |
2 -> error; | |
3 -> unknown | |
end, | |
indicator_color => case ColorInd of | |
0 -> off; | |
1 -> changing; | |
2 -> on | |
end, | |
filter => FilterDust | |
}, | |
#{state => State, mode => Mode, temperature => TempCurrent, temp_target => TempTarget, | |
humidity => Humidity, humidity_target => HumidityTarget, speed => Speed, speed_fact => SpeedFact, | |
speed_target => SpeedTarget, | |
misc => Misc, time => {Year+2000,Month,Day,Hour,Min,0}, day_of_week => Dow, msg => Msg}; | |
parse2(<<"VZL0",Zone:1/binary>>, [<<VAVMixControlV:1, VAVControlV:3, VAVStateV:4, VAVIcon:8>>, | |
<<LevelFact:8, LevelTarget:8>>, CO2_]) -> | |
CO2 = binary_to_integer(CO2_), | |
VavState = case VAVStateV of | |
0 -> disabled; | |
1 -> ok; | |
2 -> no_link; | |
3 -> has_errors | |
end, | |
VavControl = case VAVControlV of | |
0 -> local_sensor; | |
1 -> center; | |
2 when VAVMixControlV == 0 -> mixed_local; | |
2 when VAVMixControlV == 1 -> mixed_center; | |
3 -> co2; | |
4 -> local_dry; | |
5 -> auto_mix | |
end, | |
#{zone => binary_to_integer(Zone), vav_state => VavState, vav_control => VavControl, vav_icon => VAVIcon, | |
level_target => LevelTarget, level_fact => LevelFact, co2 => CO2}. | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment