-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathphpParticle.class.php
819 lines (748 loc) · 29.2 KB
/
phpParticle.class.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
<?php
/*
* @project phpParticle
* @file phpParticle.class.php
* @authors Harrison Jones ([email protected])
* Devin Pearson ([email protected])
* @date March 12, 2015
* @brief PHP Class for interacting with the Particle Cloud (particle.io)
*/
class phpParticle
{
private $_email = false;
private $_password = false;
private $_accessToken = false;
private $_debug = false;
private $_disableSSL = true;
private $_error = "No Error";
private $_errorSource = "None";
private $_result = false;
private $_debugType = "HTML";
private $_endpoint = "https://api.particle.io/";
private $_curlTimeout = 10;
private $_productSlug = "";
/**
* Sets the api endpoint used. Default is the particle.io api
*
* @param string $endpoint A url for the api you want to use (default: "https://api.particle.io/")
*
* @return void
*
*/
public function setEndpoint($endpoint)
{
$this->_endpoint = $endpoint;
}
/**
* Sets the timeout used for calls against the api.
*
* @param int $timeout The amount of time, in seconds, for a call to wait for data before returning with a TIMEOUT error
*
* @return void
*
*/
public function setTimeout($timeout)
{
if(is_numeric($timeout))
{
$this->_curlTimeout = intval($timeout);
return true;
}
else
{
$errorText = "Non numeric timeout";
$this->_setError($errorText, __FUNCTION__);
return false;
}
}
/**
* Sets the authentication details for authenticating with the API
*
* @param string $email The email to authenticate with
* @param string $password The password to authenticate with
*
* @return void
*
*/
public function setAuth($email, $password)
{
$this->_email = $email;
$this->_password = $password;
}
/**
* Clears all the authentication info (email and password). Internally set to false. Subsequent calls which require a email/password will fail
*
* @return void
*
*/
public function clearAuth()
{
$this->setAuth(false,false);
}
/**
* Sets the access token for authenticating with the API
*
* @param string $accessToken The access token to authenticate with
*
* @return void
*
*/
public function setAccessToken($accessToken)
{
$this->_accessToken = $accessToken;
}
/**
* Sets the product slug for authenticating with the API
*
* @param string $accessToken The access token to authenticate with
*
* @return void
*
*/
public function setProductSlug($productSlug)
{
$this->_productSlug = $productSlug;
}
/**
* Clears the accesss token info. Internally set to false. Subsequent calls which require an access token will fail
*
* @return void
*
*/
public function clearAccessToken()
{
$this->setAccessToken(false);
}
/**
* Sets the debug type. Use "HTML" for errors automatically formatted for embedding into a webpage and "TEXT" for unformatted raw errors
*
* @param string $debugType The debug type (either "HTML" or "TEXT")
*
* @return void
*
*/
public function setDebugType($debugType = "HTML")
{
if(($debugType == "HTML") or ($debugType == "TEXT"))
{
$this->_debugType = $debugType;
return true;
}
else
{
$this->_setError("Bad debut type (" . $debugType . ")", "setDebugType");
return false;
}
}
/**
* Turn internal debugging on or off. Note, external calls made to debug ($obj->debug(...)) will always display regardless of this setting
*
* @param boolean $debug true turns on internal debugging & false turns off internal debugging
*
* @return void
*
*/
public function setDebug($debug = false)
{
if($debug)
{
$this->_debug = true;
return true;
}
else
{
$this->_debug = false;
return true;
}
}
/**
* Turn on or off SSL verification (it's a CURL thing). For testing, before you get the certificates setup, you might need to disable SSL verificatioon. Note this is a security concern
*
* @param boolean $disableSSL true allows you to communicate with api endpoints with invalid security certificates & false enforces SSL verification
*
* @return void
*
*/
public function setDisableSSL($disableSSL = false)
{
if($disableSSL)
{
$this->_disableSSL = true;
return true;
}
else
{
$this->_disableSSL = false;
return true;
}
}
/**
* Private Function. Sets the internal _error & _errorSource variables. Allow for tracking which function resulted in an error and what that error was
*
* @param string $errorText The value to set _error to
* @param string $errorSource The value to set _errorSource to
*
* @return void
*
*/
private function _setError($errorText, $errorSource)
{
$this->_error = $errorText;
$this->_errorSource = $errorSource;
}
/**
* Private Function. Sets the internal _errorSource. Allow for tracking which function resulted in an error
*
* @param string $errorSource The value to set _errorSource to
*
* @return void
*
*/
private function _setErrorSource($errorSource)
{
$this->_errorSource = $errorSource;
}
/**
* Private Function. Outputs the desired debug text formatted if required
*
* @param string $debugText The debug string to output
* @param string $override If set to true overrides the internal debug on/off state and always outputs the debugText. If set to false it follows the internal debug on/off state
*
* @return void
*
*/
private function _debug($debugText, $override = false)
{
if(($this->_debug == true) || ($override == true))
{
if($this->_debugType == "HTML")
{
echo $debugText . "<BR/>\n";
return true;
}
else if($this->_debugType == "TEXT")
{
echo $debugText . "\n";
return true;
}
else
{
$this->_setError("Bad debut type (" . $this->_debugType . ")", "_debug");
return false;
}
}
}
/**
* Private Function. Outputs the desired debug array formatted if required
*
* @param mixed[] $debugArray The debug array to output
* @param string $override If set to true overrides the internal debug on/off state and always outputs the debugArray. If set to false it follows the internal debug on/off state
*
* @return void
*
*/
private function _debug_r($debugArray, $override = false)
{
if(($this->_debug == true) || ($override == true))
{
if($this->_debugType == "HTML")
{
$this->debug("<pre>");
print_r($debugArray);
$this->debug("</pre>");
return true;
}
else if($this->_debugType == "TEXT")
{
print_r($debugArray);
$this->debug();
return true;
}
else
{
$this->_setError("Bad debut type (" . $this->_debugType . ")", "_debug");
return false;
}
}
}
/**
* Outputs the desired debug text formatted if required
*
* @param string $debugText The debug string to output
*
* @return void
*
*/
public function debug($debugText)
{
return $this->_debug($debugText, $override = true);
}
/**
* Outputs the desired debug array formatted if required
*
* @param string $debugArray The debug array to output
*
* @return void
*
*/
public function debug_r($debugArray)
{
return $this->_debug_r($debugArray, $override = true);
}
/**
* Runs a particle function on the device. Requires the accessToken to be set
*
* @param string $deviceID The device ID of the device to call the function on
* @param string $deviceFunction The name function to call
* @param string $params The parameters to send to the function (the 'args')
*
* @return boolean true if the call was successful, false otherwise. Use getResult to get the api result and use getError & getErrorSource to determine what happened in the event of an error
*/
public function callFunction($deviceID, $deviceFunction, $params)
{
if(empty($this->_productSlug)) {
$url = $this->_endpoint . 'v1/devices/' . $deviceID . '/' . $deviceFunction;
} else {
$url = $this->_endpoint . 'v1/products/' . $this->_productSlug . '/devices/' . $deviceID . '/' . $deviceFunction;
}
return $this->_curlRequest($url, array('args'=>$params), 'post');
}
/**
* Gets the value of a particle variable. Requires the accessToken to be set
*
* @param string $deviceID The device ID of the device to call the function on
* @param string $variableName The name of the variable to retrieve
*
* @return boolean true if the call was successful, false otherwise. Use getResult to get the api result and use getError & getErrorSource to determine what happened in the event of an error
*/
public function getVariable($deviceID, $variableName)
{
if(empty($this->_productSlug)) {
$url = $this->_endpoint . 'v1/devices/' . $deviceID . '/' . $variableName;
} else {
$url = $this->_endpoint . 'v1/products/' . $this->_productSlug . '/devices/' . $deviceID . '/' . $variableName;
}
return $this->_curlRequest($url, array(), 'get');
}
/**
* Lists all your cores assigned to your cloud account. Requires the accessToken to be set
*
* @return boolean true if the call was successful, false otherwise. Use getResult to get the api result and use getError & getErrorSource to determine what happened in the event of an error
*/
public function listDevices()
{
if(empty($this->_productSlug)) {
$url = $this->_endpoint . 'v1/devices/';
return $this->_curlRequest($url, array(), 'get');
} else {
$url = $this->_endpoint . 'v1/products/' . $this->_productSlug . '/devices/';
return $this->_curlRequest($url, array(), 'get', 'none', 'devices');
}
}
/**
* Gets your details from your core e.g. function and variables. Requires the accessToken to be set
*
* @param string $deviceID The device ID of the device
*
* @return boolean true if the call was successful, false otherwise. Use getResult to get the api result and use getError & getErrorSource to determine what happened in the event of an error
*/
public function getAttributes($deviceID)
{
if(empty($this->_productSlug)) {
$url = $this->_endpoint . 'v1/devices/' . $deviceID;
} else {
$url = $this->_endpoint . 'v1/products/' . $this->_productSlug . '/devices/' . $deviceID;
}
return $this->_curlRequest($url, array(), 'get');
}
/**
* Set the name/renames your core. Requires the accessToken to be set
*
* @param string $deviceID The device ID of the device to rename
* @param string $name The new name of the device
*
* @return boolean true if the call was successful, false otherwise. Use getResult to get the api result and use getError & getErrorSource to determine what happened in the event of an error
*/
public function renameCore($deviceID,$name)
{
if(empty($this->_productSlug)) {
$url = $this->_endpoint . 'v1/devices/' . $deviceID;
} else {
$url = $this->_endpoint . 'v1/products/' . $this->_productSlug . '/devices/' . $deviceID;
}
return $this->_curlRequest($url, array("name" => $name), 'put');
}
/**
* Attempts to add a device to your cloud account. Requires the accessToken to be set. Note, you may want to follow this up with a call to "setName" as new Core's names are blank. Interestingly, if claiming an order core their name is retained across the unclaim/claim process
*
* @param string $deviceID The device ID of the device to claim.
* @param boolean $requestTransfer If true requests that the device be transfered to your account (use if the device is already claimed). If false will try to claim but not automatically send a transfer request
*
* @return boolean true if the call was successful, false otherwise. Use getResult to get the api result and use getError & getErrorSource to determine what happened in the event of an error
*/
public function claimDevice($deviceID, $requestTransfer = false)
{
if(empty($this->_productSlug)) {
$url = $this->_endpoint . 'v1/devices';
} else {
$url = $this->_endpoint . 'v1/products/' . $this->_productSlug . '/devices';
}
if($requestTransfer)
$result = $this->_curlRequest($url, array('id' => $deviceID, 'request_transfer' => 'true'), 'post');
else
$result = $this->_curlRequest($url, array('id' => $deviceID, 'request_transfer' => 'false'), 'post');
return $result;
}
/**
* Removes the core from your cloud account. Requires the accessToken to be set
*
* @param string $deviceID The device ID of the device to remove from your account.
*
* @return boolean true if the call was successful, false otherwise. Use getResult to get the api result and use getError & getErrorSource to determine what happened in the event of an error
*/
public function removeDevice($deviceID)
{
if(empty($this->_productSlug)) {
$url = $this->_endpoint . 'v1/devices/' . $deviceID;
} else {
$url = $this->_endpoint . 'v1/products/' . $this->_productSlug . '/devices/' . $deviceID;
}
return $this->_curlRequest($url, array(), 'delete');
}
/**
* Uploads a sketch to the core. Requires the accessToken to be set
*
* @param string $deviceID The device ID of the device to upload the code to
* @param string $filename The filename of the firmware file to upload to the device. Ex: tinker.cpp. Not yet implemented
* @param string $filepath The path to the firmware file to upload (including the name). Ex: path/to/tinker.cpp
* @param boolean $isBinary Set to true if uploading a .bin file or false otherwise.
*
* @return boolean true if the call was successful, false otherwise. Use getResult to get the api result and use getError & getErrorSource to determine what happened in the event of an error
*/
public function uploadFirmware($deviceID,$filename,$filepath,$isBinary=false)
{
if(empty($this->_productSlug)) {
$url = $this->_endpoint . 'v1/devices/' . $deviceID;
} else {
$url = $this->_endpoint . 'v1/products/' . $this->_productSlug . '/devices/' . $deviceID;
}
// Create a CURLFile object
$cfile = new CURLFile($filepath,'application/octet-stream',$filename);
$params = array('file' => $cfile);
if($isBinary == true)
$params['file_type'] = "binary";
return $this->_curlRequest($url, $params, 'put-file');
}
/**
* Gets a list of your tokens from the particle cloud. Requires the email/password auth to be set
*
* @return boolean true if the call was successful, false otherwise. Use getResult to get the api result and use getError & getErrorSource to determine what happened in the event of an error
*/
public function listAccessTokens()
{
$url = $this->_endpoint .'v1/access_tokens';
$result = $this->_curlRequest($url, array(), 'get', 'basic');
return $result;
}
/**
* Creates a new token on the particle cloud. Requires the email/password auth to be set
*
* @param int $expires_in When the token should expire (in seconds). Set to false to ignore and use the default. Set to 0 for a token that never expires
* @param string $expires_at When the token should expire (at a date/time). Set to false to ignore and use the default. Set to 'null' for a token that never expires. Otherwise this should be a ISO8601 style date string
* @param string $clientID The clientID. If you don't have one of these (only used in OAuth applications) set to false
* @param string $clientSecret The clientSecret. If you don't have one of these (only used in OAuth applications) set to false
*
* @return boolean true if the call was successful, false otherwise. Use getResult to get the api result and use getError & getErrorSource to determine what happened in the event of an error
*/
public function newAccessToken($expires_in = false, $expires_at = false, $clientID = false, $clientSecret = false)
{
$fields = array('grant_type' => 'password', 'username' => $this->_email, 'password' => $this->_password);
if($expires_in !== false)
$fields['expires_in'] = intval($expires_in);
if($expires_at !== false)
$fields['expires_at'] = $expires_at;
if($clientID)
{
$fields['client_id'] = $clientID;
$fields['client_secret'] = $clientSecret;
}
$url = $this->_endpoint .'oauth/token';
$result = $this->_curlRequest($url, $fields, 'post', 'basic-dummy');
return $result;
}
/**
* Removes the token from the particle cloud. Requires the email/password auth to be set
*
* @param string $token The access token to remove
*
* @return boolean true if the call was successful, false otherwise. Use getResult to get the api result and use getError & getErrorSource to determine what happened in the event of an error
*/
public function deleteAccessToken($token)
{
$url = $this->_endpoint .'v1/access_tokens/'.$token;
$result = $this->_curlRequest($url, array(), 'delete', 'basic');
return $result;
}
/**
* Gets a list of webhooks from the particle cloud. Requires the accessToken to be set
*
* @return boolean true if the call was successful, false otherwise. Use getResult to get the api result and use getError & getErrorSource to determine what happened in the event of an error
*/
public function listWebhooks()
{
$fields = array();
$url = $this->_endpoint .'v1/webhooks';
$result = $this->_curlRequest($url, $fields, 'get');
return $result;
}
/**
* Creates a new webhook on the particle cloud. Requires the accessToken to be set
* @param string $event The event name used to trigger the webhook
* @param string $webhookUrl The url to query once the event has occured
* @param string $extras See http://docs.particle.io/webhooks/#webhook-options
*
* @return boolean true if the call was successful, false otherwise. Use getResult to get the api result and use getError & getErrorSource to determine what happened in the event of an error
*/
public function newWebhook($event, $webhookUrl, $extras = array())
{
$url = $this->_endpoint .'v1/webhooks/';
$fields = array_merge(array('event' => $event, 'url' => $webhookUrl),$extras);
$result = $this->_curlRequest($url, $fields , 'post');
return $result;
}
/**
* Delete webhooks from the particle cloud. Requires the accessToken to be set
*
* @return boolean true if the call was successful, false otherwise. Use getResult to get the api result and use getError & getErrorSource to determine what happened in the event of an error
*/
public function deleteWebhook($webhookID)
{
$fields = array();
$url = $this->_endpoint ."v1/webhooks/{$webhookID}/";
$result = $this->_curlRequest($url, $fields, 'delete');
return $result;
}
/**
* Sets the particle core signal mode state. Requires the accessToken to be set
*
* @param string $deviceID The device ID of the device to send the signal mode state change command to.
* @param int $signalState The signal state: 0 returns the RGB led back to normmal & 1 makes it flash a rainbow of color
*
* @return boolean true if the call was successful, false otherwise. Use getResult to get the api result and use getError & getErrorSource to determine what happened in the event of an error
*/
public function signalDevice($deviceID, $signalState = 0)
{
if(empty($this->_productSlug)) {
$url = $this->_endpoint . 'v1/devices/' . $deviceID;
} else {
$url = $this->_endpoint . 'v1/products/' . $this->_productSlug . '/devices/' . $deviceID;
}
$fields = array('signal' => $signalState);
return $this->_curlRequest($url, $fields, 'put');
}
/**
* Returns the latest error
*
* @return string The latest error
*/
public function getError()
{
return $this->_error;
}
/**
* Returns the latest error's source (which function cause the error)
*
* @return string The latest error's source
*/
public function getErrorSource()
{
return $this->_errorSource;
}
/**
* Returns the latest result
*
* @return string The latest result from calling a cloud function
*/
public function getResult()
{
return $this->_result;
}
/**
* Private Function. Performs a CURL Request with the given parameters
*
* @param string url The url to call
* @param mixed[] params An array of parameters to pass to the url
* @param string type The type of request ("GET", "POST", "PUT", etc)
* @param string authType The type of authorization to use ('none' uses the access token, 'basic' uses basic auth with the email/password auth details, and 'basic-dummy' uses dummy basic auth details)
*
* @return boolean true on success, false on failure
*/
private function _curlRequest($url, $params = null, $type = 'post', $authType = 'none', $key = false)
{
$fields_string = null;
if($authType == 'none')
if ($this->_accessToken)
{
$params['access_token'] = $this->_accessToken;
}
else
{
$errorText = "No access token set";
list(, $caller) = debug_backtrace(false);
$this->_setError($errorText, $caller['function']);
return false;
}
// is cURL installed yet?
if (!function_exists('curl_init'))
{
die("CURL is not installed/available");
}
// OK cool - then let's create a new cURL resource handle
$ch = curl_init();
//set the number of POST vars, POST data
if($type == 'get')
{
$url .= ("?" . http_build_query($params));
}
else if ($type == 'post')
{
curl_setopt($ch,CURLOPT_POST,count($params));
curl_setopt($ch,CURLOPT_POSTFIELDS,http_build_query($params));
}
else if($type == "put")
{
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
curl_setopt($ch,CURLOPT_POSTFIELDS,http_build_query($params));
}
else if($type == "put-file")
{
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
unset($params['access_token']);
curl_setopt($ch,CURLOPT_POSTFIELDS,$params);
$url .= "?access_token=" . $this->_accessToken;
}
else if ($type == 'delete')
{
$url .= ("?" . http_build_query($params));
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "DELETE");
}
else
{
$errorText = "Unsupported method type (" . $type . ")";
$this->_setError($errorText, __FUNCTION__);
return false;
}
$this->_debug("Opening a {$type} connection to {$url}");
curl_setopt($ch, CURLOPT_URL, $url);
if($this->_disableSSL)
{
// stop the verification of certificate
$this->_debug("[WARN] Disabling SSL Verification for CURL");
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
}
// Set a referer
// curl_setopt($ch, CURLOPT_REFERER, "http://www.example.com/curl.htm");
// User agent
// curl_setopt($ch, CURLOPT_USERAGENT, "MozillaXYZ/1.0");
// Include header in result? (0 = yes, 1 = no)
curl_setopt($ch, CURLOPT_HEADER, 0);
// Should cURL return or print out the data? (true = return, false = print)
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// Timeout in seconds
curl_setopt($ch, CURLOPT_TIMEOUT, $this->_curlTimeout);
$this->_debug("Auth Type: " . $authType);
// basic auth
if ($authType == 'basic') {
if(($this->_email) && ($this->_password))
{
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_USERPWD, $this->_email . ":" . $this->_password);
}
else
{
list(, $caller) = debug_backtrace(false);
$errorText = "No auth credentials (email/password) set";
$this->_setError($errorText, $caller['function']);
return false;
}
}
if ($authType == 'basic-dummy') {
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_USERPWD, "particle:particle");
}
// Download the given URL, and return output
$this->_debug("Executing Curl Operation");
$this->_debug("Url:");
$this->_debug_r($url);
$this->_debug("Params:");
$this->_debug_r($params);
$output = curl_exec($ch);
$this->_debug("Curl Result: '" . $output . "'");
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$this->_debug("Curl Response Code: '" . $httpCode."'");
// Close the cURL resource, and free system resources
$curlError = curl_errno($ch);
curl_close($ch);
if($curlError != CURLE_OK)
{
$this->_debug("CURL Request - There was a CURL error");
list(, $caller) = debug_backtrace(false);
//var_dump($caller['function']);
$errorText = $this->_curlErrorCode($curlError);
$this->_setError($errorText, $caller['function']);
return false;
}
else
{
$retVal = json_decode($output,true);
if(json_last_error() == 0)
{
if(isset($retVal['error']) && $retVal['error'])
{
$this->_debug("CURL Request - API response contained 'error' field");
$errorText = $retVal['error'];
$this->_setError($errorText, __FUNCTION__);
return false;
}
else
{
$this->_debug("CURL Request - Returning True");
if($key != false) {
$this->_debug("CURL Request - Extracting from key '" . $key . "'");
$this->_result = $retVal[$key];
} else {
$this->_result = $retVal;
}
return true;
}
}
else
{
$this->_debug("CURL Request - Unable to parse JSON");
$errorText = "Unable to parse JSON. Json error = " . json_last_error() . ". See http://php.net/manual/en/function.json-last-error.php for more information. Raw response from Particle Cloud = '" . $result . "'";
$this->_setError($errorText, __FUNCTION__);
return false;
}
}
}
/**
* Private Function. Returns a human readable string for a given CURL Error Code
*
* @param int curlCode The CURL error code
*
* @return string A human-readable string version of the curlCode
*/
private function _curlErrorCode($curlCode)
{
switch ($curlCode)
{
case 26:
return "Curl Error. There was a problem reading a local file or an error returned by the read callback.";
case 30:
return "Curl Error. Operation timeout. The specified time-out period was reached according to the conditions.";
default:
return "Curl Error. Error number = {$curlCode}. See http://curl.haxx.se/libcurl/c/libcurl-errors.html for more information";
}
}
}