Completed
Push — master ( 060a6c...9bcf1c )
by Chris
02:52
created

MessageEncoder::encodeSetLabel()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
ccs 0
cts 3
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php declare(strict_types=1);
2
3
namespace DaveRandom\LibLifxLan\Encoding;
4
5
use DaveRandom\LibLifxLan\DataTypes as DeviceDataTypes;
6
use DaveRandom\LibLifxLan\DataTypes\Light as LightDataTypes;
7
use DaveRandom\LibLifxLan\Messages\Device\Commands as DeviceCommands;
8
use DaveRandom\LibLifxLan\Messages\Device\Requests as DeviceRequests;
9
use DaveRandom\LibLifxLan\Messages\Device\Responses as DeviceResponses;
10
use DaveRandom\LibLifxLan\Messages\Light\Commands as LightCommands;
11
use DaveRandom\LibLifxLan\Messages\Light\Responses as LightResponses;
12
use DaveRandom\LibLifxLan\Messages\Message;
13
use DaveRandom\LibLifxLan\Messages\UnknownMessage;
14
use const DaveRandom\LibLifxLan\FLOAT32_CODE;
15
use function DaveRandom\LibLifxLan\datetimeinterface_to_nanotime;
16
use function DaveRandom\LibLifxLan\int16_to_uint16;
17
18
final class MessageEncoder
19
{
20
    /**
21
     * @uses encodeUnknownMessage
22
     * @uses encodeEchoRequest
23
     * @uses encodeEchoResponse
24
     * @uses encodeSetGroup
25
     * @uses encodeStateGroup
26
     * @uses encodeStateHostFirmware
27
     * @uses encodeStateHostInfo
28
     * @uses encodeStateInfo
29
     * @uses encodeSetLabel
30
     * @uses encodeStateLabel
31
     * @uses encodeSetLocation
32
     * @uses encodeStateLocation
33
     * @uses encodeSetDevicePower
34
     * @uses encodeStateDevicePower
35
     * @uses encodeStateService
36
     * @uses encodeStateVersion
37
     * @uses encodeStateWifiFirmware
38
     * @uses encodeStateWifiInfo
39
     * @uses encodeSetColor
40
     * @uses encodeSetWaveform
41
     * @uses encodeSetWaveformOptional
42
     * @uses encodeState
43
     * @uses encodeSetInfrared
44
     * @uses encodeStateInfrared
45
     * @uses encodeSetLightPower
46
     * @uses encodeStateLightPower
47
     */
48
    private const ENCODING_ROUTINES = [
49
        UnknownMessage::class => 'UnknownMessage',
50
51
        // Device command messages
52
        DeviceCommands\SetGroup::class => 'SetGroup',
53
        DeviceCommands\SetLabel::class => 'SetLabel',
54
        DeviceCommands\SetLocation::class => 'SetLocation',
55
        DeviceCommands\SetPower::class => 'SetDevicePower',
56
57
        // Device request messages
58
        DeviceRequests\EchoRequest::class => 'EchoRequest',
59
60
        // Device response messages
61
        DeviceResponses\EchoResponse::class => 'EchoResponse',
62
        DeviceResponses\StateGroup::class => 'StateGroup',
63
        DeviceResponses\StateHostFirmware::class => 'StateHostFirmware',
64
        DeviceResponses\StateHostInfo::class => 'StateHostInfo',
65
        DeviceResponses\StateInfo::class => 'StateInfo',
66
        DeviceResponses\StateLabel::class => 'StateLabel',
67
        DeviceResponses\StateLocation::class => 'StateLocation',
68
        DeviceResponses\StatePower::class => 'StateDevicePower',
69
        DeviceResponses\StateService::class => 'StateService',
70
        DeviceResponses\StateVersion::class => 'StateVersion',
71
        DeviceResponses\StateWifiFirmware::class => 'StateWifiFirmware',
72
        DeviceResponses\StateWifiInfo::class => 'StateWifiInfo',
73
74
        // Light command messages
75
        LightCommands\SetColor::class => 'SetColor',
76
        LightCommands\SetInfrared::class => 'SetInfrared',
77
        LightCommands\SetPower::class => 'SetLightPower',
78
        LightCommands\SetWaveform::class => 'SetWaveform',
79
        LightCommands\SetWaveformOptional::class => 'SetWaveformOptional',
80
81
        // Light response messages
82
        LightResponses\State::class => 'State',
83
        LightResponses\StateInfrared::class => 'StateInfrared',
84
        LightResponses\StatePower::class => 'StateLightPower',
85
    ];
86
87
    private function encodeHsbkColor(LightDataTypes\HsbkColor $color): string
88
    {
89
        return \pack('v4', $color->getHue(), $color->getSaturation(), $color->getBrightness(), $color->getTemperature());
90
    }
91
92
    private function encodeLocation(DeviceDataTypes\Location $location): string
93
    {
94
        return \pack(
95
            'a16a32P',
96
            $location->getGuid()->getBytes(),
97
            $location->getLabel()->getValue(),
98
            datetimeinterface_to_nanotime($location->getUpdatedAt())
99
        );
100
    }
101
102
    private function encodeGroup(DeviceDataTypes\Group $group): string
103
    {
104
        return \pack(
105
            'a16a32P',
106
            $group->getGuid()->getBytes(),
107
            $group->getLabel()->getValue(),
108
            datetimeinterface_to_nanotime($group->getUpdatedAt())
109
        );
110
    }
111
112
    private function encodeFirmware(DeviceDataTypes\Firmware $firmware)
113
    {
114
        return \pack(
115
            'PPV',
116
            datetimeinterface_to_nanotime($firmware->getBuild()),
117
            0, // reserved
118
            $firmware->getVersion()
119
        );
120
    }
121
122
    private function encodeNetworkInfo(DeviceDataTypes\NetworkInfo $info): string
123
    {
124
        return \pack(
125
            FLOAT32_CODE . 'VVv',
126
            $info->getSignal(),
127
            $info->getTx(),
128
            $info->getRx(),
129
            0 // reserved
130
        );
131
    }
132
133
    private function encodeUnknownMessage(UnknownMessage $message): string
134
    {
135
        return $message->getData();
136
    }
137
138
    private function encodeStateVersion(DeviceResponses\StateVersion $message): string
139
    {
140
        $version = $message->getVersion();
141
142
        return \pack('VVV', $version->getVendor(), $version->getProduct(), $version->getVersion());
143
    }
144
145
    private function encodeStateService(DeviceResponses\StateService $message): string
146
    {
147
        $service = $message->getService();
148
149
        return \pack('CV', $service->getTypeId(), $service->getPort());
150
    }
151
152
    private function encodeStateInfo(DeviceResponses\StateInfo $message): string
153
    {
154
        $info = $message->getInfo();
155
156
        return \pack('PPP', datetimeinterface_to_nanotime($info->getTime()), $info->getUptime(), $info->getDowntime());
157
    }
158
159
    private function encodeStateHostFirmware(DeviceResponses\StateHostFirmware $message): string
160
    {
161
        return $this->encodeFirmware($message->getHostFirmware());
162
    }
163
164
    private function encodeStateHostInfo(DeviceResponses\StateHostInfo $message): string
165
    {
166
        return $this->encodeNetworkInfo($message->getHostInfo());
167
    }
168
169
    private function encodeStateWifiFirmware(DeviceResponses\StateWifiFirmware $message): string
170
    {
171
        return $this->encodeFirmware($message->getWifiFirmware());
172
    }
173
174
    private function encodeStateWifiInfo(DeviceResponses\StateWifiInfo $message): string
175
    {
176
        return $this->encodeNetworkInfo($message->getWifiInfo());
177
    }
178
179
    private function encodeSetGroup(DeviceCommands\SetGroup $message): string
180
    {
181
        return $this->encodeGroup($message->getGroup());
182
    }
183
184
    private function encodeStateGroup(DeviceResponses\StateGroup $message): string
185
    {
186
        return $this->encodeGroup($message->getGroup());
187
    }
188
189
    private function encodeSetLabel(DeviceCommands\SetLabel $message): string
190
    {
191
        return \pack('a32', $message->getLabel()->getValue());
192
    }
193
194
    private function encodeStateLabel(DeviceResponses\StateLabel $message): string
195
    {
196
        return \pack('a32', $message->getLabel()->getValue());
197
    }
198
199
    private function encodeSetLocation(DeviceCommands\SetLocation $message): string
200
    {
201
        return $this->encodeLocation($message->getLocation());
202
    }
203
204
    private function encodeStateLocation(DeviceResponses\StateLocation $message): string
205
    {
206
        return $this->encodeLocation($message->getLocation());
207
    }
208
209
    private function encodeSetDevicePower(DeviceCommands\SetPower $message): string
210
    {
211
        return \pack('v', $message->getLevel());
212
    }
213
214
    private function encodeStateDevicePower(DeviceResponses\StatePower $message): string
215
    {
216
        return \pack('v', $message->getLevel());
217
    }
218
219
    private function encodeEchoRequest(DeviceRequests\EchoRequest $message): string
220
    {
221
        return $message->getPayload();
222
    }
223
224
    private function encodeEchoResponse(DeviceResponses\EchoResponse $message): string
225
    {
226
        return $message->getPayload();
227
    }
228
229
    private function encodeSetColor(LightCommands\SetColor $message): string
230
    {
231
        $transition = $message->getColorTransition();
232
233
        return "\x00" . $this->encodeHsbkColor($transition->getColor()) . \pack('V', $transition->getDuration());
234
    }
235
236
    private function encodeSetInfrared(LightCommands\SetInfrared $message): string
237
    {
238
        return \pack('v', $message->getBrightness());
239
    }
240
241
    private function encodeStateInfrared(LightResponses\StateInfrared $message): string
242
    {
243
        return \pack('v', $message->getBrightness());
244
    }
245
246
    private function encodeSetLightPower(LightCommands\SetPower $message): string
247
    {
248
        $transition = $message->getPowerTransition();
249
250
        return \pack('vV', $transition->getLevel(), $transition->getDuration());
251
    }
252
253
    private function encodeStateLightPower(LightResponses\StatePower $message): string
254
    {
255
        return \pack('v', $message->getLevel());
256
    }
257
258
    private function encodeState(LightResponses\State $message): string
259
    {
260
        $state = $message->getState();
261
262
        return $this->encodeHsbkColor($state->getColor()) . \pack(
263
            'v2a32P',
264
            0, // reserved
265
            $state->getPower(),
266
            $state->getLabel()->getValue(),
267
            0  // reserved
268
        );
269
    }
270
271
    private function encodeSetWaveform(LightCommands\SetWaveform $message): string
272
    {
273
        $effect = $message->getEffect();
274
        $skew = int16_to_uint16($effect->getSkewRatio());
275
276
        return "\x00" . \chr((int)$effect->isTransient())
277
            . $this->encodeHsbkColor($effect->getColor())
278
            . \pack('V' . FLOAT32_CODE . 'vC', $effect->getPeriod(), $effect->getCycles(), $skew, $effect->getWaveform())
279
        ;
280
    }
281
282
    private function encodeSetWaveformOptional(LightCommands\SetWaveformOptional $message): string
283
    {
284
        $effect = $message->getEffect();
285
        $skew = int16_to_uint16($effect->getSkewRatio());
286
287
        $options = $effect->getOptions();
288
        $optionData = \pack(
289
            'C4',
290
            (int)(bool)($options & LightDataTypes\Effect::SET_HUE),
291
            (int)(bool)($options & LightDataTypes\Effect::SET_SATURATION),
292
            (int)(bool)($options & LightDataTypes\Effect::SET_BRIGHTNESS),
293
            (int)(bool)($options & LightDataTypes\Effect::SET_TEMPERATURE)
294
        );
295
296
        return "\x00" . \chr((int)$effect->isTransient())
297
            . $this->encodeHsbkColor($effect->getColor())
298
            . \pack('V' . FLOAT32_CODE . 'vC', $effect->getPeriod(), $effect->getCycles(), $skew, $effect->getWaveform())
299
            . $optionData
300
        ;
301
    }
302
303
    public function encodeMessage(Message $message): string
304
    {
305
        return \array_key_exists($class = \get_class($message), self::ENCODING_ROUTINES)
306
            ? $this->{'encode' . self::ENCODING_ROUTINES[$class]}($message)
307
            : '';
308
    }
309
}
310