首页 > 代码库 > 使用Erlang UDP做仿真通信
使用Erlang UDP做仿真通信
-module(udpserver).
-import(crc,[comCrc16/1]).
-export([start/0,client/1]). %%服务端
start()->
spawn(fun()->
server(19997) end).%%开启进程执行server函数 19997
server(Port)->
{ok, Socket} = gen_udp:open(Port, [binary, {active, false}]),%%打开udp端口
io:format("server open socket:~p~n", [Socket]),%%输出内容
loop(Socket).%%调用loop函数
loop(Socket)->
inet:setopts(Socket, [{active, once}]),%%启动Socket
receive
{udp, Socket, Host, Port, Bin} ->
io:format("server received:~p~n", [Bin]),
{Identity, ReceiveBin} = getReceiveBin(Bin),
io:format("server send:~p~n", [ReceiveBin]),
gen_udp:send(Socket, Host, Port, ReceiveBin),
sendSlaveRequest(Socket, Host, Port, Identity, Bin),
loop(Socket)
end.
getReceiveBin(Bin) ->
Arr = binary_to_list(Bin),
[_,_,_,Identity,Len,SerialNum|_Others] = Arr,
case Identity of
16#02 ->
Res = [16#A5,16#5A,16#00,Identity,16#9,SerialNum,16#1],
Crc = crc:comCrc16(Res),
{Identity, Res ++ Crc};
16#06 ->
Res = [16#A5,16#5A,16#00,Identity,16#9,SerialNum,16#1],
Crc = crc:comCrc16(Res),
%%io:format("CRC:~p~n", [Crc]),%%输出内容
{Identity, Res ++ Crc};
16#23 ->
Res = [16#A5,16#5A,16#00,Identity,16#9,SerialNum,16#1],
Crc = crc:comCrc16(Res),
{Identity, Res ++ Crc};
16#07 ->
DataLen = (Len - 8) * 8,
<<_First:48,Data:DataLen,_Crc:16>> = Bin,%%从位数组中截取内如,每个字节8位,First截取前6个字节
%%io:format("Data:~p~n", [Data]), %%输出内容
[16#A5,16#5A,16#00,16#07,Len,16#00,16#11,0,0];
Other ->
{Identity, Arr}
end.
sleep(T) ->
receive
after T ->
ok
end.
%上发下位机请求
sendSlaveRequest(Socket, Host, Port, Identity, Bin) ->
case Identity of
16#02 ->
sendFeedback(Socket, Host, Port, Bin);
Other ->
ok
end.
%发送调剂动作反馈
sendFeedback(Socket, Host, Port, Bin) ->
sleep(1000),
ListData = http://www.mamicode.com/binary_to_list(Bin),
[_,_,_,Identity,Len,SerialNo|_T] = ListData,
OtherLen = (Len-16)*8, <<_:48, _:80,Others:OtherLen>> = Bin,
%% io:format("CrcAndPulse****:~p~n", [Others]),
[P1, P2, P3, P4] = getPulseCnt(Others, OtherLen),
%io:format("P1--P4: ~p, ~p, ~p, ~p ~n", [P1, P2, P3, P4]),
NewSerialNo = if SerialNo >=255 -> 0; true -> SerialNo + 1 end,
Body = getFeedbackBody(Bin, OtherLen),
Request = [16#D3, 16#3D, 16#00, 16#85, 16#12, NewSerialNo] ++ Body,
Crc = crc:comCrc16(Request),
RequestList = Request ++ Crc,
%%io:format("sendFeedback****(begin) ~p~n", [RequestList]),
gen_udp:send(Socket, Host, Port, RequestList),
io:format("sendFeedback****(end) ~p~n", [RequestList]).
getFeedbackBody(Bin, OtherLen)->
<<_:48, _:4,IsTurnOffBottle_Ap1:1,_:1,IsAdmix_AP1:1,IsPluginBottle_Ap1:1,
%%注意 按位运算的时候,字节是反序的,高位在前,低位在后
_:4,IsTurnOffBottle_Ap2:1,_:1,IsAdmix_AP2:1,IsPluginBottle_Ap2:1, _:4,IsTurnOffBottle_Ap3:1,_:1,IsAdmix_AP3:1,IsPluginBottle_Ap3:1,
_:4,IsTurnOffBottle_Ap4:1,_:1,IsAdmix_AP4:1,IsPluginBottle_Ap4:1, BoxTurnDirection:1,_:2,BoxTurnCnt:5, CellTurnCnt:3,_:4,CellTurnDirection:1,
PushBoxInfo:8, _:5,IsCutoffFilm:1,IsEncBox:1,IsPushFilm:1, _:8,_:8,Others:OtherLen>> = Bin,
AP1 = calcAdmixpartFeedback(IsPluginBottle_Ap1,IsAdmix_AP1,IsTurnOffBottle_Ap1),
AP2 = calcAdmixpartFeedback(IsPluginBottle_Ap2,IsAdmix_AP2,IsTurnOffBottle_Ap2),
AP3 = calcAdmixpartFeedback(IsPluginBottle_Ap3,IsAdmix_AP3,IsTurnOffBottle_Ap3),
AP4 = calcAdmixpartFeedback(IsPluginBottle_Ap4,IsAdmix_AP4,IsTurnOffBottle_Ap4),
io:format("***admixpart command:IsTurnOffBottle_Ap4:~p,IsAdmix_AP4:~p,IsPluginBottle_Ap4:~p ~n", [IsTurnOffBottle_Ap4,IsAdmix_AP4,IsPluginBottle_Ap4]),
BoxRotate = case BoxTurnCnt > 0 of true -> (BoxTurnDirection bsl 7) bor BoxTurnCnt; _ -> 0 end,
CellRotate = case CellTurnCnt > 0 of true -> (CellTurnDirection bsl 7) bor CellTurnCnt; _ -> 0 end,
IsPushInBox = PushBoxInfo band 16#01,
IsPushOutBox = (PushBoxInfo bsr 1) band 16#01,
BoxOther = PushBoxInfo band 16#3F,
%%io:format("++++IsPushInBox:~p IsPushOutBox:~p BoxOther:~p ~n", [IsPushInBox,IsPushOutBox,BoxOther]),
PushBox = (IsPushOutBox bsl 1) bor IsPushInBox,
Enc = if IsEncBox =:= 1 -> 2#111; true -> 0 end,
Body = [AP1, AP2, AP3, AP4, BoxRotate, CellRotate, PushBox, Enc, 0, 0].
calcAdmixpartFeedback(IsPluginBottle,IsAdmix,IsTurnOffBottle) ->
B1 = if IsPluginBottle =:= 1 -> 1; true -> 0 end,
B2 = if IsAdmix =:= 1 -> 2#111; true -> 0 end,
B3 = if IsTurnOffBottle =:= 1 -> 1; true -> 0 end,
(B3 bsl 4) bor (B2 bsl 1) bor B1. getPulseCnt(Crc, 16)-> [0,0,0,0];
getPulseCnt(Crc, 48)->
[Crc bsr 16,0,0,0];
getPulseCnt(Crc, 80)->
[Crc bsr 48,(Crc bsr 16) band 16#FFFFFFFF,0,0];
getPulseCnt(Crc, 112)->
[Crc bsr 80, (Crc bsr 48) band 16#FFFFFFFF, (Crc bsr 16) band 16#FFFFFFFF,0];
getPulseCnt(Crc, 144)->
[Crc bsr 112, (Crc bsr 80) band 16#FFFFFFFF, (Crc bsr 48) band 16#FFFFFFFF, (Crc bsr 16) band 16#FFFFFFFF]. %%客户端
client(N) ->
{Res, Socket} = gen_udp:open(0, [binary]),
io:format("client opened socket:~p ~p~n", [Res, Socket]),
ok = gen_udp:send(Socket, "localhost", 4000, N),
Value = http://www.mamicode.com/receive
{udp, Socket, _, _, Bin} ->
io:format("client received:~p~n", [Bin])
after
2000 -> 0
end,
gen_udp:close(Socket),
Value.
使用Erlang UDP做仿真通信