-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsearch.xml
1153 lines (560 loc) · 351 KB
/
search.xml
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
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title>图解TCP通讯</title>
<link href="//post/tcp-detail.html"/>
<url>//post/tcp-detail.html</url>
<content type="html"><![CDATA[<h2 id="1、引言"><a href="#1、引言" class="headerlink" title="1、引言"></a>1、引言</h2><p>网络编程能力对于即时通讯技术开发者来说是基本功,而计算机网络又是网络编程的理论根基,因而深刻准确地理解计算机网络知识显然能夯实你的即时通讯应用的实践品质。</p><h2 id="2、系列文章"><a href="#2、系列文章" class="headerlink" title="2、系列文章"></a>2、系列文章</h2><p>本文是该系列文章中的第2篇:</p><ul><li><a href="http://www.52im.net/thread-3330-1-1.html">《网络编程入门从未如此简单(一):假如你来设计网络,会怎么做?》</a></li><li><a href="http://www.52im.net/thread-3339-1-1.html">《网络编程入门从未如此简单(二):假如你来设计TCP协议,会怎么做?》</a>(本文)</li></ul><p>本文主要涉及计算机网络的传输层,希望让TCP协议的学习不再枯燥和生涩。</p><h2 id="3、初识传输层"><a href="#3、初识传输层" class="headerlink" title="3、初识传输层"></a>3、初识传输层</h2><p>你是一台电脑,你的名字叫 A</p><img src="/post/tcp-detail/001.webp" class="" title="you are a computer"><p>经过<a href="https://mp.weixin.qq.com/s?__biz=Mzk0MjE3NDE0Ng==&mid=2247489907&idx=1&sn=a296cb42467cab6f0a7847be32f52dae&chksm=c2c663def5b1eac84b664c8c1cadf1c8ec23ea2e57e48e04add9b833c841256fc9449b62c0ec&scene=21#wechat_redirect">《如果让你来设计网络》</a>这篇文章中的一番折腾,只要你知道另一位伙伴 B 的 IP 地址,且你们之间的网络是通的,无论多远,你都可以将一个数据包发送给你的伙伴 B</p><img src="/post/tcp-detail/v2-002.webp" class="" title="A Complex NetWork"><p>这就是物理层、数据链路层、网络层这三层所做的事情。</p><p>站在第四层的你,就可以不要脸地利用下三层所做的铺垫,随心所欲地发送数据,而不必担心找不到对方了。</p><img src="/post/tcp-detail/640.gif" class=""><p>虽然你此时还什么都没干,但你还是给自己这一层起了个响亮的名字,叫做<strong>传输层</strong>。</p><p>你本以为自己所在的第四层万事大吉,啥事没有,但很快问题就接踵而至。</p><h2 id="4、问题来了"><a href="#4、问题来了" class="headerlink" title="4、问题来了"></a>4、问题来了</h2><p>前三层协议只能把数据包从一个主机搬到另外一台主机,但是,到了目的地以后,数据包具体交给哪个程序(进程)呢?</p><img src="/post/tcp-detail/640.png" class=""><p>所以,你需要把通信的进程区分开来,于是就给每个进程分配一个数字编号,你给它起了一个响亮的名字:<strong>端口号</strong>。</p><img src="/post/tcp-detail/002.png" class=""><p>然后你在要发送的数据包上,增加了传输层的头部,<strong>源端口号</strong>与<strong>目标端口号</strong>。</p><img src="/post/tcp-detail/003.png" class=""><p>OK,这样你将原本主机到主机的通信,升级为了<strong>进程和进程之间的通信</strong>。<br>你没有意识到,你不知不觉实现了 <strong>UDP 协议</strong>!</p><ul><li>(当然 UDP 协议中不光有源端口和目标端口,还有数据包长度和校验值,我们暂且略过)</li></ul><p>就这样,你用 UDP 协议无忧无虑地同 B 进行着通信,一直没发生什么问题。</p><img src="/post/tcp-detail/002.gif" class=""><p>但很快,你发现事情变得非常复杂……</p><h2 id="5、丢包问题"><a href="#5、丢包问题" class="headerlink" title="5、丢包问题"></a>5、丢包问题</h2><p>由于网络的不可靠,数据包可能在半路丢失,而 A 和 B 却无法察觉。</p><img src="/post/tcp-detail/003.gif" class=""><p>对于丢包问题,只要解决两个事就好了。</p><pre><code>第一个,A 怎么知道包丢了? 答案:让 B 告诉 A第二个,丢了的包怎么办? 答案:重传</code></pre><p>于是你设计了如下方案,A 每发一个包,都必须收到来自 B 的确认(ACK),再发下一个,否则在一定时间内没有收到确认,就重传这个包。</p><img src="/post/tcp-detail/004.gif" class=""><p>你管它叫<strong>停止等待协议</strong>。只要按照这个协议来,虽然 A 无法保证 B 一定能收到包,但 A 能够确认 B 是否收到了包,收不到就重试,尽最大努力让这个通信过程变得可靠,于是你们现在的通信过程又有了一个新的特征,<strong>可靠交付</strong>。</p><h2 id="6、效率问题"><a href="#6、效率问题" class="headerlink" title="6、效率问题"></a>6、效率问题</h2><p>停止等待虽然能解决问题,但是效率太低了,A 原本可以在发完第一个数据包之后立刻开始发第二个数据包,但由于停止等待协议,A 必须等数据包到达了 B ,且 B 的 ACK 包又回到了 A,才可以继续发第二个数据包,这效率慢得可不是一点两点。</p><p>于是你对这个过程进行了改进,采用流水线的方式,不再傻傻地等。</p><img src="/post/tcp-detail/005.gif" class=""><h2 id="7、顺序问题"><a href="#7、顺序问题" class="headerlink" title="7、顺序问题"></a>7、顺序问题</h2><p>但是网路是复杂的、不可靠的。</p><p>有的时候 A 发出去的数据包,分别走了不同的路由到达 B,可能无法保证和发送数据包时一样的顺序。</p><img src="/post/tcp-detail/006.gif" class=""><p>在流水线中有多个数据包和ACK包在<strong>乱序流动</strong>,他们之间对应关系就乱掉了。</p><p>难道还回到停止等待协议?A 每收到一个包的确认(ACK)再发下一个包,那就根本不存在顺序问题。应该有更好的办法!</p><p>A 在发送的数据包中增加一个序号(seq),同时 B 要在 ACK 包上增加一个<strong>确认号</strong>(ack),这样不但解决了停止等待协议的效率问题,也通过这样标序号的方式解决了顺序问题。</p><img src="/post/tcp-detail/007.gif" class=""><p>而 B 这个确认号意味深长:比如 B 发了一个确认号为 ack = 3,它不仅仅表示 A 发送的序号为 2 的包收到了,还表示 2 之前的数据包都收到了。这种方式叫<strong>累计确认</strong>或<strong>累计应答</strong>。</p><img src="/post/tcp-detail/008.gif" class=""><ul><li>注意,实际上 ack 的号是收到的最后一个数据包的序号 seq + 1,也就是告诉对方下一个应该发的序号是多少。但图中为了便于理解,ack 就表示收到的那个序号,不必纠结。</li></ul><h2 id="8、流量问题"><a href="#8、流量问题" class="headerlink" title="8、流量问题"></a>8、流量问题</h2><p>有的时候,A 发送数据包的速度太快,而 B 的接收能力不够,但 B 却没有告知 A 这个情况。</p><img src="/post/tcp-detail/009.gif" class=""><p>怎么解决呢?</p><p>很简单,B 告诉 A 自己的<strong>接收能力</strong>,A 根据 B 的<strong>接收能力</strong>,相应控制自己的发送速率,就好了。</p><p>B 怎么告诉 A 呢?B 跟 A 说”我很强”这三个字么?那肯定不行,得有一个严谨的规范。</p><p>于是 B 决定,每次发送数据包给 A 时,顺带传过来一个值,叫<strong>窗口大小</strong>(win),这个值就表示 B 的接收能力。同理,每次 A 给 B 发包时也带上自己的窗口大小,表示 A 的接收能力。</p><img src="/post/tcp-detail/010.gif" class=""><p>B 告诉了 A 自己的窗口大小值,A 怎么利用它去做 A 这边发包的流量控制呢?</p><p>很简单,假如 B 给 A 传过来的窗口大小 win = 5,那 A 根据这个值,把自己要发送的数据分成这么几类。</p><img src="/post/tcp-detail/004.png" class=""><p>图片过于清晰,就不再文字解释了。</p><p>当 A 不断发送数据包时,已发送的最后一个序号就往右移动,直到碰到了窗口的上边界,此时 A 就无法继续发包,达到了流量控制。</p><img src="/post/tcp-detail/011.gif" class=""><p>但是当 A 不断发包的同时,A 也会收到来自 B 的确认包,此时整个窗口会往右移动,因此上边界也往右移动,A 就能发更多的数据包了。</p><img src="/post/tcp-detail/012.gif" class=""><p>以上都是在窗口大小不变的情况下,而 B 在发给 A 的 ACK 包中,每一个都可以重新设置一个新的窗口大小,如果 A 收到了一个新的窗口大小值,A 会随之调整。</p><p>如果 A 收到了比原窗口值更大的窗口大小,比如 win = 6,则 A 会直接将窗口上边界向右移动 1 个单位。</p><img src="/post/tcp-detail/013.gif" class=""><p>如果 A 收到了比原窗口值小的窗口大小,比如 win = 4,则 A 暂时不会改变窗口大小,更不会将窗口上边界向左移动,而是等着 ACK 的到来,不断将左边界向右移动,直到窗口大小值收缩到新大小为止。</p><img src="/post/tcp-detail/014.gif" class=""><p>OK,终于将流量控制问题解决得差不多了,你看着上面一个个小动图,给这个窗口起了一个更生动的名字,<strong>滑动窗口</strong>。</p><h2 id="9、拥塞问题"><a href="#9、拥塞问题" class="headerlink" title="9、拥塞问题"></a>9、拥塞问题</h2><p>但有的时候,不是 B 的接受能力不够,而是网络不太好,造成了<strong>网络拥塞</strong>。</p><img src="/post/tcp-detail/015.gif" class=""><p>拥塞控制与流量控制有些像,但流量控制是受 B 的接收能力影响,而拥塞控制是受网络环境的影响。</p><p>拥塞控制的解决办法依然是通过设置一定的窗口大小,只不过,流量控制的窗口大小是 B 直接告诉 A 的,而拥塞控制的窗口大小按理说就应该是网络环境主动告诉 A。</p><p>但网络环境怎么可能主动告诉 A 呢?只能 A 单方面通过试探,不断感知网络环境的好坏,进而确定自己的拥塞窗口的大小。</p><img src="/post/tcp-detail/016.gif" class=""><p>拥塞窗口大小的计算有很多复杂的算法,就不在本文中展开了,假如<strong>拥塞窗口</strong>的大小为 cwnd,上一部分流量控制的<strong>滑动窗口</strong>的大小为 rwnd,那么窗口的右边界受这两个值共同的影响,需要取它俩的最小值。</p><pre><code> 窗口大小 = min(cwnd, rwnd)</code></pre><p>含义很容易理解,当 B 的接受能力比较差时,即使网络非常通畅,A 也需要根据 B 的接收能力限制自己的发送窗口。当网络环境比较差时,即使 B 有很强的接收能力,A 也要根据网络的拥塞情况来限制自己的发送窗口。正所谓受其短板的影响嘛~</p><h2 id="10、连接问题"><a href="#10、连接问题" class="headerlink" title="10、连接问题"></a>10、连接问题</h2><p>有的时候,B 主机的相应进程还没有准备好或是挂掉了,A 就开始发送数据包,导致了浪费。</p><img src="/post/tcp-detail/017.gif" class=""><p>这个问题在于,A 在跟 B 通信之前,没有事先确认 B 是否已经准备好,就开始发了一连串的信息。就好比你和另一个人打电话,你还没有”喂”一下确认对方有没有在听,你就巴拉巴拉说了一堆。</p><p>这个问题该怎么解决呢?</p><p>地球人都知道,<strong>三次握手</strong>嘛!</p><pre><code>A:我准备好了(SYN)B:我知道了(ACK),我也准备好了(SYN)A:我知道了(ACK)</code></pre><img src="/post/tcp-detail/018.gif" class=""><p>A 与 B 各自在内存中维护着自己的状态变量,三次握手之后,双方的状态都变成了<strong>连接已建立</strong>(ESTABLISHED)。</p><p>虽然就只是发了三次数据包,并且在各自的内存中维护了状态变量,但这么说总觉得太 low,你看这个过程相当于双方建立连接的过程,于是你灵机一动,就叫它<strong>面向连接</strong>吧。</p><ul><li>注意:这个连接是虚拟的,是由 A 和 B 这两个终端共同维护的,在网络中的设备根本就不知道连接这回事儿!</li></ul><p>但凡事有始就有终,有了建立连接的过程,就要考虑释放连接的过程,又是地球人都知道,<strong>四次挥手</strong>嘛!</p><pre><code>A:再见,我要关闭了(FIN)B:我知道了(ACK) (给 B 一段时间把自己的事情处理完...)B:再见,我要关闭了(FIN)A:我知道了(ACK)</code></pre><img src="/post/tcp-detail/019.gif" class=""><h2 id="11、总结"><a href="#11、总结" class="headerlink" title="11、总结"></a>11、总结</h2><p>以上讲述的,就是 TCP 协议的核心思想,上面过程中需要传输的信息,就体现在 TCP 协议的头部,这里放上最常见的 TCP 协议头解读的图。</p><img src="/post/tcp-detail/006.png" class=""><p>不知道你现在再看下面这句话,是否能理解:</p><p><strong>TCP 是</strong></p><p><strong>面向连接的、可靠的、基于字节流的</strong></p><p><strong>传输层通信协议</strong></p><p>面向连接、可靠,这两个词通过上面的讲述很容易理解,那什么叫做基于字节流呢?</p><p>很简单,TCP 在建立连接时,需要告诉对方 MSS(最大报文段大小)。</p><p>也就是说,如果要发送的数据很大,在 TCP 层是需要按照 MSS 来切割成一个个的 <strong>TCP 报文段</strong> 的。</p><p>切割的时候我才不管你原来的数据表示什么意思,需要在哪里断句啥的,我就把它当成一串毫无意义的字节,在我想要切割的地方咔嚓就来一刀,标上序号,只要接收方再根据这个序号拼成最终想要的完整数据就行了。</p><p>在我 TCP 传输这里,我就把它当做一个个的字节,也就是基于字节流的含义了。</p><p>最后留给大家一个作业,模拟 A 与 B 建立一个 TCP 连接。</p><p>第一题:A 给 B 发送 “aaa” ,然后 B 给 A 回复一个简单的字符串 “success”,并将此过程抓包。</p><p>第二题:A 给 B 发送 “aaaaaa … a” 超过最大报文段大小,然后 B 给 A 回复一个简单的字符串 “success”,并将此过程抓包。</p><p>下面是我抓的包(第二题)</p><pre><code>三次握手阶段A -> B [SYN] Seq=0 Win=64240 Len=0 MSS=1460 WS=256B - >A [SYN, ACK] Seq=0 Ack=1 Win=29200 Len=0 MSS=1424 WS=512A -> B [ACK] Seq=1 Ack=1 Win=132352 Len=0数据发送阶段A -> B [ACK] Seq=1 Ack=1 Win=132352 Len=1424A -> B [ACK] Seq=1425 Ack=1 Win=132352 Len=1424A -> B [PSH, ACK] Seq=2849 Ack=1 Win=132352 Len=1247B -> A [ACK] Seq=1 Ack=1425 Win=32256 Len=0B -> A [ACK] Seq=1 Ack=2849 Win=35328 Len=0B -> A [ACK] Seq=1 Ack=4096 Win=37888 Len=0B -> A [PSH, ACK] Seq=1 Ack=4096 Win=37888 Len=7四次挥手阶段B -> A [FIN, ACK] Seq=8 Ack=4096 Win=37888 Len=0A -> B [ACK] Seq=4096 Ack=9 Win=132352 Len=0A -> B [FIN, ACK] Seq=4096 Ack=9 Win=132352 Len=0</code></pre><h2 id="12、后记"><a href="#12、后记" class="headerlink" title="12、后记"></a>12、后记</h2><p>一提到 TCP,可能很多人都想起被三次握手和四次挥手所支配的恐惧。但其实你跟着文中的思路你就会发现,三次握手与四次挥手只占 TCP 所解决的核心问题中很小的一部分,只是因为它在面试中很适合作为知识点进行考察,所以在很多人的印象中就好像 TCP 的核心就是握手和挥手似的。</p><p>本文希望你能从问题出发,真正理解 TCP 所想要解决的问题,你会发现很多原理就好像生活常识一样顺其自然,并不复杂,希望你有收获~</p><p><a href="https://mp.weixin.qq.com/s/h89R86KhWiQKsBvfZpyF5Q">原文</a></p>]]></content>
<categories>
<category> tcp </category>
</categories>
<tags>
<tag> tcp </tag>
<tag> 网络 </tag>
</tags>
</entry>
<entry>
<title>Clash 基本配置记录</title>
<link href="//post/clashx.html"/>
<url>//post/clashx.html</url>
<content type="html"><![CDATA[<h3 id="一、规则解释"><a href="#一、规则解释" class="headerlink" title="一、规则解释"></a>一、规则解释</h3><ul><li>DOMAIN-SUFFIX:域名后缀匹配</li><li>DOMAIN:域名匹配</li><li>DOMAIN-KEYWORD:域名关键字匹配</li><li>IP-CIDR:IP段匹配</li><li>SRC-IP-CIDR:源IP段匹配</li><li>GEOIP:GEOIP数据库(国家代码)匹配</li><li>DST-PORT:目标端口匹配</li><li>SRC-PORT:源端口匹配</li><li>MATCH:全匹配(一般放在最后)</li></ul><h3 id="二、基本配置"><a href="#二、基本配置" class="headerlink" title="二、基本配置"></a>二、基本配置</h3><div class="custom-quote tip"><span class="custom-quote-svg"><svg width="24" height="24" viewBox="0 0 24 24" fill="" xmlns="http://www.w3.org/2000/svg" data-reactroot=""><path fill="" d="M20.86 14.13C20 14.7 19.56 15.74 19.77 16.76C20.13 18.55 18.55 20.13 16.76 19.77C15.74 19.57 14.7 20 14.13 20.86C13.12 22.38 10.89 22.38 9.88 20.86C9.3 20 8.26 19.56 7.24 19.77C5.45 20.13 3.87 18.55 4.23 16.76C4.43 15.74 4 14.7 3.14 14.13C1.62 13.12 1.62 10.89 3.14 9.88C4 9.3 4.44 8.26 4.23 7.24C3.87 5.45 5.45 3.87 7.24 4.23C8.26 4.44 9.3 4 9.87 3.14C10.88 1.62 13.11 1.62 14.12 3.14C14.7 4 15.74 4.44 16.76 4.23C18.55 3.87 20.13 5.45 19.77 7.24C19.56 8.26 20 9.3 20.86 9.87C22.38 10.88 22.38 13.12 20.86 14.13Z" undefined="1"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M12.01 15C12.01 14.5 12.01 14.5 12.01 14.5C12.04 13.75 13 13.46 14.04 12.2C14.41 11.74 14.69 11.41 14.86 10.85C15.15 9.95 14.92 9.18 14.86 9.02C14.8 8.79 14.52 8 13.72 7.46C13.06 7.02 12.42 7 12.14 7C11.9 7 11.36 7 10.78 7.3C10.28 7.56 9.98 7.9 9.83 8.1C9.24 8.82 9.06 9.63 9 10.06"></path><path stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M11.99 18H12.01"></path></svg></span><p class="custom-quote-title">提示</p><p>Normal Tips Container</p></div><pre class="line-numbers language-YAML" data-language="YAML"><code class="language-YAML">#---------------------------------------------------# ## 配置文件需要放置在 $HOME/.config/clash/config.yml ## ## 如果您不知道如何操作,请参阅 SS-Rule-Snippet 的 Wiki: ## https://github.com/Hackl0us/SS-Rule-Snippet/wiki/clash(X) #---------------------------------------------------# # HTTP 代理端口 port: 7890 # SOCKS5 代理端口 socks-port: 7891 # Linux 和 macOS 的 redir 代理端口 (如需使用此功能,请取消注释) # redir-port: 7892 # 允许局域网的连接(可用来共享代理) allow-lan: false # bind-address: "*" # 此功能仅在 allow-lan 设置为 true 时生效,支持三种参数: # "*" 绑定所有的 IP 地址 # 192.168.122.11 绑定一个的 IPv4 地址 # "[aaaa::a8aa:ff:fe09:57d8]" 绑定一个 IPv6 地址 # 规则模式:Rule(规则) / Global(全局代理)/ Direct(全局直连) mode: Rule # 设置日志输出级别 (默认级别:silent,即不输出任何内容,以避免因日志内容过大而导致程序内存溢出)。 # 5 个级别:silent / info / warning / error / debug。级别越高日志输出量越大,越倾向于调试,若需要请自行开启。 log-level: silent # clash 的 RESTful API external-controller: 127.0.0.1:9090 # 您可以将静态网页资源(如 clash-dashboard)放置在一个目录中,clash 将会服务于 `${API}/ui` # 参数应填写配置目录的相对路径或绝对路径。 # external-ui: folder # RESTful API 的口令 (可选) # secret: "" # 实验性功能 experimental: ignore-resolve-fail: true # 忽略 DNS 解析失败,默认值为 true # 本地 SOCKS5 / HTTP(S) 服务认证 # authentication: # - "user1:pass1" # - "user2:pass2" # # 实验性功能 hosts, 支持通配符 (例如 *.clash.dev 甚至 *.foo.*.example.com) # # 静态的域名 比 通配域名 具有更高的优先级 (foo.example.com 优先于 *.example.com) # # 注意: hosts 在 fake-ip 模式下不生效 # hosts: # '*.clash.dev': 127.0.0.1 # 'alpha.clash.dev': '::1' dns: enable: true ipv6: false # listen: 0.0.0.0:53 # enhanced-mode: redir-host # 或 fake-ip # # fake-ip-range: 198.18.0.1/16 # 如果你不知道这个参数的作用,请勿修改 # fake-ip-filter: # fake-ip 白名单列表 # - '*.lan' # - localhost.ptlogin2.qq.com nameserver: - 1.2.4.8 - 114.114.114.114 - 223.5.5.5 - tls://13800000000.rubyfish.cn:853 #- https://13800000000.rubyfish.cn/ fallback: # 与 nameserver 内的服务器列表同时发起请求,当规则符合 GEOIP 在 CN 以外时,fallback 列表内的域名服务器生效。 - tls://13800000000.rubyfish.cn:853 - tls://1.0.0.1:853 - tls://dns.google:853 #- https://13800000000.rubyfish.cn/ #- https://cloudflare-dns.com/dns-query #- https://dns.google/dns-query fallback-filter: geoip: true # 默认 ipcidr: # 在这个网段内的 IP 地址会被考虑为被污染的 IP - 240.0.0.0/4 # 1. clash DNS 请求逻辑: # (1) 当访问一个域名时, nameserver 与 fallback 列表内的所有服务器并发请求,得到域名对应的 IP 地址。 # (2) clash 将选取 nameserver 列表内,解析最快的结果。 # (3) 若解析结果中,IP 地址属于 国外,那么 clash 将选择 fallback 列表内,解析最快的结果。 # # 因此,我在 nameserver 和 fallback 内都放置了无污染、解析速度较快的国内 DNS 服务器,以达到最快的解析速度。 # 但是 fallback 列表内服务器会用在解析境外网站,为了结果绝对无污染,我仅保留了支持 DoT/DoH 的两个服务器。 # # 2. clash DNS 配置注意事项: # (1) 如果您为了确保 DNS 解析结果无污染,请仅保留列表内以 tls:// 或 https:// 开头的 DNS 服务器,但是通常对于国内域名没有必要。 # (2) 如果您不在乎可能解析到污染的结果,更加追求速度。请将 nameserver 列表的服务器插入至 fallback 列表内,并移除重复项。 # # 3. 关于 DNS over HTTPS (DoH) 和 DNS over TLS (DoT) 的选择: # 对于两项技术双方各执一词,而且会无休止的争论,各有利弊。各位请根据具体需求自行选择,但是配置文件内默认启用 DoT,因为目前国内没有封锁或管制。 # DoH: 以 https:// 开头的 DNS 服务器。拥有更好的伪装性,且几乎不可能被运营商或网络管理封锁,但查询效率和安全性可能略低。 # DoT: 以 tls:// 开头的 DNS 服务器。拥有更高的安全性和查询效率,但端口有可能被管制或封锁。 # 若要了解更多关于 DoH/DoT 相关技术,请自行查阅规范文档。 Proxy: # shadowsocks # 所支持的加密方式与 go-shadowsocks2 保持一致 # 支持加密方式: # aes-128-gcm aes-192-gcm aes-256-gcm # aes-128-cfb aes-192-cfb aes-256-cfb # aes-128-ctr aes-192-ctr aes-256-ctr # rc4-md5 chacha20 chacha20-ietf xchacha20 # chacha20-ietf-poly1305 xchacha20-ietf-poly1305 - name: "ss1" type: ss server: server port: 443 cipher: chacha20-ietf-poly1305 password: "password" # udp: true - name: "ss2" type: ss server: server port: 443 cipher: AEAD_CHACHA20_POLY1305 password: "password" plugin: obfs plugin-opts: mode: tls # 混淆模式,可以选择 http 或 tls host: bing.com # 混淆域名,需要和服务器配置保持一致 - name: "ss3" type: ss server: server port: 443 cipher: AEAD_CHACHA20_POLY1305 password: "password" plugin: v2ray-plugin plugin-opts: mode: websocket # 暂时不支持 QUIC 协议 # tls: true # wss # skip-cert-verify: true # host: bing.com # path: "/" # headers: # custom: value # vmess # 支持加密方式:auto / aes-128-gcm / chacha20-poly1305 / none - name: "vmess" type: vmess server: server port: 443 uuid: uuid alterId: 32 cipher: auto # udp: true # tls: true # skip-cert-verify: true # network: ws # ws-path: /path # ws-headers: # Host: v2ray.com # socks5 - name: "socks" type: socks5 server: server port: 443 # username: username # password: password # tls: true # skip-cert-verify: true # udp: true # http - name: "http" type: http server: server port: 443 # username: username # password: password # tls: true # https # skip-cert-verify: true # snell - name: "snell" type: snell server: server port: 44046 psk: yourpsk # obfs-opts: # mode: http # 或 tls # host: bing.com Proxy Group: # url-test 可以自动选择与指定 URL 测速后,延迟最短的服务器 - name: "auto" type: url-test proxies: - ss1 - ss2 - vmess1 url: 'http://www.gstatic.com/generate_204' interval: 300 # fallback 可以尽量按照用户书写的服务器顺序,在确保服务器可用的情况下,自动选择服务器 - name: "fallback-auto" type: fallback proxies: - ss1 - ss2 - vmess1 url: 'http://www.gstatic.com/generate_204' interval: 300 # load-balance 可以使相同 eTLD 请求在同一条代理线路上 - name: "load-balance" type: load-balance proxies: - ss1 - ss2 - vmess1 url: 'http://www.gstatic.com/generate_204' interval: 300 # select 用来允许用户手动选择 代理服务器 或 服务器组 # 您也可以使用 RESTful API 去切换服务器,这种方式推荐在 GUI 中使用 - name: Proxy type: select proxies: - ss1 - ss2 - vmess1 - auto Rule: # 抗 DNS 污染 - DOMAIN-KEYWORD,amazon,Proxy - DOMAIN-KEYWORD,google,Proxy - DOMAIN-KEYWORD,gmail,Proxy - DOMAIN-KEYWORD,youtube,Proxy - DOMAIN-KEYWORD,facebook,Proxy - DOMAIN-SUFFIX,fb.me,Proxy - DOMAIN-SUFFIX,fbcdn.net,Proxy - DOMAIN-KEYWORD,twitter,Proxy - DOMAIN-KEYWORD,instagram,Proxy - DOMAIN-KEYWORD,dropbox,Proxy - DOMAIN-SUFFIX,twimg.com,Proxy - DOMAIN-KEYWORD,blogspot,Proxy - DOMAIN-SUFFIX,youtu.be,Proxy - DOMAIN-KEYWORD,whatsapp,Proxy # 常见广告域名屏蔽 - DOMAIN-KEYWORD,admarvel,REJECT - DOMAIN-KEYWORD,admaster,REJECT - DOMAIN-KEYWORD,adsage,REJECT - DOMAIN-KEYWORD,adsmogo,REJECT - DOMAIN-KEYWORD,adsrvmedia,REJECT - DOMAIN-KEYWORD,adwords,REJECT - DOMAIN-KEYWORD,adservice,REJECT - DOMAIN-KEYWORD,domob,REJECT - DOMAIN-KEYWORD,duomeng,REJECT - DOMAIN-KEYWORD,dwtrack,REJECT - DOMAIN-KEYWORD,guanggao,REJECT - DOMAIN-KEYWORD,lianmeng,REJECT - DOMAIN-SUFFIX,mmstat.com,REJECT - DOMAIN-KEYWORD,omgmta,REJECT - DOMAIN-KEYWORD,openx,REJECT - DOMAIN-KEYWORD,partnerad,REJECT - DOMAIN-KEYWORD,pingfore,REJECT - DOMAIN-KEYWORD,supersonicads,REJECT - DOMAIN-KEYWORD,uedas,REJECT - DOMAIN-KEYWORD,umeng,REJECT - DOMAIN-KEYWORD,usage,REJECT - DOMAIN-KEYWORD,wlmonitor,REJECT - DOMAIN-KEYWORD,zjtoolbar,REJECT # LAN - DOMAIN-SUFFIX,local,DIRECT - IP-CIDR,127.0.0.0/8,DIRECT - IP-CIDR,172.16.0.0/12,DIRECT - IP-CIDR,192.168.0.0/16,DIRECT - IP-CIDR,10.0.0.0/8,DIRECT - IP-CIDR,17.0.0.0/8,DIRECT - IP-CIDR,100.64.0.0/10,DIRECT # 最终规则 - GEOIP,CN,DIRECT - MATCH,Proxy</code></pre><h3 id="三、绕过系统代理"><a href="#三、绕过系统代理" class="headerlink" title="三、绕过系统代理"></a>三、绕过系统代理</h3><p>Clash for Windows在v 0.4.5 版本后可以自定义系统代理需要绕过的域名或IP</p><p>部分应用检测到系统代理会拒绝响应(例如网易云音乐uwp),此功能用于解决此类问题</p><p>设置方式<br>config.yaml</p><pre class="line-numbers language-YAML" data-language="YAML"><code class="language-YAML">port: 8888 socks-port: 8889 redir-port: 0 allow-lan: true mode: Rule log-level: info external-controller: '0.0.0.0:6170' secret: '' Proxy: ... Proxy Group: ... Rule: ... cfw-bypass: ... # 原有字段不用删除 - 'music.163.com' # 网易云域名1 - '*.music.126.net' # 网易云域名2</code></pre><p>cfw-bypass类型为数组,item为需要绕过的域名或节点,支持通配符*</p><blockquote><span class="custom-blockquote-svg"><svg width="24" height="24" viewBox="0 0 24 24" fill="" xmlns="http://www.w3.org/2000/svg" data-reactroot=""><path fill="" d="M22 12C22 6.5 17.5 2 12 2C6.5 2 2 6.5 2 12C2 17.5 6.5 22 12 22C13.8 22 15.5 21.5 17 20.6L22 22L20.7 17C21.5 15.5 22 13.8 22 12Z" undefined="1"></path><path fill="" d="M15.97 11.5H16.04C17.12 11.5 18 12.38 18 13.47V13.53C18 14.62 17.12 15.5 16.03 15.5H15.96C14.88 15.5 14 14.62 14 13.53V13.46C14 12.38 14.88 11.5 15.97 11.5Z" undefined="1"></path><path fill="" d="M7.97 11.5H8.04C9.12 11.5 10 12.38 10 13.47V13.53C10 14.62 9.12 15.5 8.03 15.5H7.97C6.88 15.5 6 14.62 6 13.53V13.46C6 12.38 6.88 11.5 7.97 11.5Z" undefined="1"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M17 8.5C15.23 8.97 14.07 10.84 14.01 13.27C14 13.33 14 13.4 14 13.47V13.5"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M9 8.5C7.23 8.97 6.07 10.84 6.01 13.27C6 13.33 6 13.4 6 13.47V13.5"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M15.97 11.5H16.04C17.12 11.5 18 12.38 18 13.47V13.53C18 14.62 17.12 15.5 16.03 15.5H15.96C14.88 15.5 14 14.62 14 13.53V13.46C14 12.38 14.88 11.5 15.97 11.5Z"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M7.97 11.5H8.04C9.12 11.5 10 12.38 10 13.47V13.53C10 14.62 9.12 15.5 8.03 15.5H7.97C6.88 15.5 6 14.62 6 13.53V13.46C6 12.38 6.88 11.5 7.97 11.5Z"></path></svg></span><p>最后一行对应系统中“请勿将代理服务器用于本地(Intranet)地址”选项,请确保此项在最底部</p></blockquote>]]></content>
<categories>
<category> linux </category>
</categories>
<tags>
<tag> clashx </tag>
</tags>
</entry>
<entry>
<title>家庭宽带开启IPV6</title>
<link href="//post/openwrt-ipv6.html"/>
<url>//post/openwrt-ipv6.html</url>
<content type="html"><![CDATA[<h1 id="常见的运营商超级管理员账号"><a href="#常见的运营商超级管理员账号" class="headerlink" title="常见的运营商超级管理员账号"></a>常见的运营商超级管理员账号</h1><h2 id="中国移动"><a href="#中国移动" class="headerlink" title="中国移动"></a>中国移动</h2><ul><li>移动光猫账号∶CMCCAdmin 密码∶ aDm8H%MdA </li><li>华为的∶telecomadmin 密码∶ admintelecom</li><li>中国移动光纤宽带ip∶192.168.100.1的超级账号∶telecomadmin 密码∶nE7jA%5m</li></ul><h2 id="中国电信"><a href="#中国电信" class="headerlink" title="中国电信"></a>中国电信</h2><ul><li>账号∶telecomadmin 密码∶ nE7jA%5m</li></ul><h1 id="设置光猫为桥接模式"><a href="#设置光猫为桥接模式" class="headerlink" title="设置光猫为桥接模式"></a>设置光猫为桥接模式</h1><p>打开IPV4/IPV6,如果设置不了,请截图保存,然后删除,再新建,然后按原来的设置(如何连接光猫,可观看前面的视频)</p><p><img src="/post/openwrt-ipv6/ipv6-1.png" alt="ipv6-1.png"></p><h1 id="然后设置软路由或者路由器"><a href="#然后设置软路由或者路由器" class="headerlink" title="然后设置软路由或者路由器"></a>然后设置软路由或者路由器</h1><h2 id="有软路由情况下:"><a href="#有软路由情况下:" class="headerlink" title="有软路由情况下:"></a>有软路由情况下:</h2><ul><li>网络——接口——IPV6 ULA清空</li><li>网络——接口——WAN口——使用内置IPV6管理取消勾选——Obtain IPv6-Address项目确保是自动状态</li><li>网络——接口——lan口——DHCP——IPV6设置——高级设置——取消勾选使用内置IPV6管理——取消勾选强制链路</li><li>通告的DNS服务器(添加谷歌IPV6DNS):<ol><li>2001:4860:4860::8888</li><li>2001:4860:4860::8844</li></ol></li></ul><p><img src="/post/openwrt-ipv6/ipv6-2.png" alt="ipv6-2.png"></p><p>混合模式会根据配置自动选择使用中继还是服务器模式。<font color="red">(这里如果是主路由请选择服务器模式,旁路由选择中继模式)</font><br>何时采用无状态、何时采用有状态,关键看应用场景。核心在于是否需要控制IP地址,比如保持IP不变,如果需要控制,就采用有状态;如果无需控制,就采用无状态。</p><ul><li><p>在DHCP/DNS——高级设置——取消勾选禁止解析IPV6 DNS记录</p></li><li><p>设置完成后一定要重启软路由</p></li><li><p>只有路由器的情况下:直接打开路由器的IPV6即可,如果有多个路由器,每个路由器都要打开</p></li><li><p>设置完成后,电脑要禁用网络然后重新启用(目的是为了获取IPV6地址)</p></li><li><p>测试IPV6:<br> <a href="https://ipv6-test.com/">https://ipv6-test.com/</a><br> <a href="https://test-ipv6.com/index.html.zh_CN">https://test-ipv6.com/index.html.zh_CN</a></p></li></ul><p> <video src="ipv6.mp4" style="width: 100%; height: 100%;" controls="controls"></video></p>]]></content>
<categories>
<category> ipv6 </category>
</categories>
<tags>
<tag> ipv6 </tag>
</tags>
</entry>
<entry>
<title>家庭光猫配置</title>
<link href="//post/mao-config.html"/>
<url>//post/mao-config.html</url>
<content type="html"><![CDATA[<div class="hbe hbe-container" id="hexo-blog-encrypt" data-wpm="Oh, this is an invalid password. Check and try again, please." data-whm="OOPS, these decrypted content may changed, but you can still have a look."> <script id="hbeData" type="hbeData" data-hmacdigest="f7a83241fffc71b5e9b66029b285fff73d423a158f5f252968550443b8971007">5ad6f12fcb346c1b5255c2a3344fe8916188cd3b15b0c898e703a6a8d3e96c9bb2622f2457644e64fd8c090fef557d91ef08e9adba24c42d7d421649e111204da34f90e46ce967daf9f81552274e1bf237128297944352b94e681eac1a3212050673923fb3b695721cf321c334a26cc3e18838af0bbac05b786a421e8be726f208a6615ad156b96fb4e41d8ce17e4e794c8ec12a618a177be8c2f98daf04a14738bc9bd40552fe60965e9b72ec08ad580bbd123a8f849295ffc919bfcdad9d93d922d0e5245823581345a6ff40b79d12a5730a66b2f48c7e559b150c184b4fee00eda1e7c6f613f6b1358fc10f5ca80b2a0afb8de504621d3dba7632d0cba7d947da7eee1be823b8ab62f20b62c4d6821a719f2dbc98b109889e532ef24a4f924a2b9e7893864deb4cba59bd46c30d9d04ea6d82d76e2bf4fb6d4d7ade322cc8e4f811c861e6b2805ee7bd05c437db27d250b5e35d42eebd625edf2761a3861e2ea77605fa485ac9d2b233908378355ce8f88844a5d9916411243234d6d4d1ade3ddf12136d4f130553d9537853c9351bfd78ed9eb574c815588097b8ce8e6a96e20dabff0d7cbf1a0ea690f5758b248188ec3c91b55fbf5d4877d42092ac6594e591d8ed55d0b2778246272d9e86401dc321ce5db0412d4534031c6d73ad4ad2613e7d86ba7ab85032871acd8c503ef39dec5afb845c19d8ef7e5052339a7baabf0d6922333b48c1fc09632597ac17cbc8238bf55e903868dbdf015184e370ce5497415c4482bfe9807064b3e6ac213d56f6dcf35ed0002acaa02f482c06634b6ff1e992dff14c31eead8880aee593adb454c7516f158d73ebae52b626b29143e8648bd8c861ddc54a2917c4130204bb0c9abc7a72c31903cab23009310dab457339af9f9238576e06ded0a57b8a529de2d90599481eb7827c8eb8cb5795aaddca41acef31efbabf95ab389093e3f4ed49fb31c5f7857f254d231f866dde10671af8d624f505236e49a59d9fccebe31ba3ae672348c30f878f8b7b2be2ceb833c11151f3dd4d8c4dfa2897a44e8b387c45672ce92a54b62587eae4cf8d68bd4974ac6523df45b6254155fb77a2fd0651e2d199305b947ea2a5b66237ae3c44e97ca14382928428102182a13a0a9c44f585bfad03140844ec721dea431e5b85e55cffd520d000320a3e91b10c9a5da01c57f3ba593de2acedaa85b0b250cf4938557b486c0e11cdb72a35f0cbe7c2721881963c44578e2db6aa578b669130709f134ea804cc7d35e8a50b812835dc3ae50347896ac7358505562ce3a02d8079a434ada066cb8368f8911b326efb8153ebd2ff1c72e59c86f2e7fa6298404277184285009d3d89c7f8f7e951a73e36223fd83fccbb7de42db23ef4bf475e9792d568f1c7fdbce16a7c04c9b2aaf314b968ddd2f42b2154b5183a824504cda6cb5cfd26506e55ae59e8d44f79cfc04457d2e3c9ebff5e433221806a63600f294deaf248470c3c69b094fae498388606f3b1e8a1a296d664fb08d44ad66a31f44fe</script> <div class="hbe hbe-content"> <div class="hbe hbe-input hbe-input-default"> <input class="hbe hbe-input-field hbe-input-field-default" type="password" id="hbePass"> <label class="hbe hbe-input-label hbe-input-label-default" for="hbePass"> <span class="hbe hbe-input-label-content hbe-input-label-content-default">Hey, password is required here.</span> </label> </div> </div></div><script data-pjax src="/lib/hbe.js"></script><link href="/css/hbe.style.css" rel="stylesheet" type="text/css">]]></content>
<categories>
<category> mao </category>
</categories>
</entry>
<entry>
<title>GoLang 全平台编译</title>
<link href="//post/go-cross-compile.html"/>
<url>//post/go-cross-compile.html</url>
<content type="html"><![CDATA[<p>Golang的全平台编译简直太爽了,真的太适合我了,平时编译一些不同设备的跨平台程序,真的是爽的不行。<br>拥有一台windows电脑就能开发出在Linux、Windows、Mac上面直接运行的程序。</p><span id="more"></span><h2 id="一、三个平台编译示例"><a href="#一、三个平台编译示例" class="headerlink" title="一、三个平台编译示例:"></a>一、三个平台编译示例:</h2><p>1、Mac下编译Linux, Windows平台的64位可执行程序:</p><pre class="line-numbers language-none"><code class="language-none">$ CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build test.go$ CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build test.go</code></pre><p>2、 Linux下编译Mac, Windows平台的64位可执行程序:</p><pre class="line-numbers language-none"><code class="language-none">$ CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build test.go$ CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build test.go</code></pre><p>3、 Windows下编译Mac, Linux平台的64位可执行程序:</p><pre class="line-numbers language-none"><code class="language-none">$ set CGO_ENABLED=0 set GOOS=darwin3 set GOARCH=amd64 go build test.go$ set CGO_ENABLED=0 set GOOS=linux s GOARCH=amd64 go build test.go</code></pre><p>当然如果编译过其他平台后,程序 go run main.go 执行会有一些问题:<br>报错如下:</p><pre class="line-numbers language-none"><code class="language-none">F:\github\syncFiles\goApi\ipDemo>go run main.gowarning: GOPATH set to GOROOT (C:\Program Files\Go) has no effectexec: "C:\\Users\\dell\\AppData\\Local\\Temp\\go-build2490838331\\b001\\exe\\main": file does not exist</code></pre><p>这里只需要:</p><pre class="line-numbers language-none"><code class="language-none">F:\github\syncFiles\goApi\ipDemo>set GOOS=windowsF:\github\syncFiles\goApi\ipDemo>go run main.gowarning: GOPATH set to GOROOT (C:\Program Files\Go) has no effect192.168.5.107</code></pre><p>main.go 是一个显示本机IP地址的程序。<br>这样做就没有问题了。</p><h2 id="二、包括三个设置的参数"><a href="#二、包括三个设置的参数" class="headerlink" title="二、包括三个设置的参数:"></a>二、包括三个设置的参数:</h2><ul><li>GOARCH:编译目标平台的硬件体系架构(amd64, 386, arm, ppc64等)。</li><li>GOOS:编译目标平台上的操作系统(darwin, freebsd, linux, windows)。</li><li>CGO_ENABLED:代表是否开启CGO,1表示开启,0表示禁用。由于CGO不能支持交叉编译,所以需要禁用。</li></ul>]]></content>
<categories>
<category> go </category>
</categories>
<tags>
<tag> go </tag>
<tag> cross </tag>
</tags>
</entry>
<entry>
<title>OpenWrt开启i2c功能,并顺利编译风扇驱动</title>
<link href="//post/openwet-i2c.html"/>
<url>//post/openwet-i2c.html</url>
<content type="html"><![CDATA[<p>树莓派安装OpenWrt作为家庭主路由,并开启i2c编译风扇、led等驱动,cpu温度骤降!~~~</p><span id="more"></span><h3 id="1、编译风扇"><a href="#1、编译风扇" class="headerlink" title="1、编译风扇"></a>1、编译风扇</h3><p>/home/uuxia/openwrt/temp_control/WiringPi-master/wiringPi</p><pre class="line-numbers language-none"><code class="language-none">/home/uuxia/openwrt/wrt/staging_dir/toolchain-aarch64_cortex-a72_gcc-8.4.0_musl/bin/aarch64-openwrt-linux-gcc \-o feng feng.c ssd1306_i2c.c \-I/home/uuxia/openwrt/temp_control/WiringPi-master/wiringPi \-L/home/uuxia/openwrt/temp_control/WiringPi-master/wiringPi \-lwiringPi</code></pre><h3 id="2、Unable-to-open-I2C-device-No-such-file-or-directory-问题解决"><a href="#2、Unable-to-open-I2C-device-No-such-file-or-directory-问题解决" class="headerlink" title="2、Unable to open I2C device: No such file or directory 问题解决"></a>2、<strong>Unable to open I2C device: No such file or directory</strong> 问题解决</h3><p>用lsmod命令可以看到i2c_bmc2708字样,但是没i2c_dev字样,那么还需要做如下处理<br>执行命令<br><code>sudo nano /etc/modules</code> # 使用nano打开文件<br>然后增加<br>i2c_dev<br>行,安Ctrl+X退出编辑,输入Y保存内容,然后重启即可。</p><h3 id="3、在OpenWrt中开启树莓派I2C功能"><a href="#3、在OpenWrt中开启树莓派I2C功能" class="headerlink" title="3、在OpenWrt中开启树莓派I2C功能"></a>3、在OpenWrt中开启树莓派I2C功能</h3><h5 id="1、编辑-x2F-boot-x2F-config-txt"><a href="#1、编辑-x2F-boot-x2F-config-txt" class="headerlink" title="1、编辑 /boot/config.txt"></a>1、编辑 /boot/config.txt</h5><pre class="line-numbers language-none"><code class="language-none">dtparam=i2c_arm=ondtparam=i2c0=ondtparam=i2c1=ondtparam=spi=ondtparam=i2s=on</code></pre><h5 id="2、通过opkg安装相关包"><a href="#2、通过opkg安装相关包" class="headerlink" title="2、通过opkg安装相关包"></a>2、通过opkg安装相关包</h5><pre class="line-numbers language-none"><code class="language-none">opkg install i2c-tools kmod-i2c-gpio kmod-i2c-algo-bit kmod-i2c-algo-pcf kmod-i2c-bcm2835 kmod-i2c-core kmod-i2c-gpio kmod-i2c-mux</code></pre><h5 id="3、使用i2c命令行工具测试"><a href="#3、使用i2c命令行工具测试" class="headerlink" title="3、使用i2c命令行工具测试"></a>3、使用i2c命令行工具测试</h5><pre class="line-numbers language-none"><code class="language-none">#!/bin/bashls /dev/i2c*i2cdetect -y 1</code></pre>]]></content>
<categories>
<category> openwrt </category>
<category> i2c </category>
</categories>
<tags>
<tag> openwrt </tag>
<tag> i2c </tag>
<tag> pi </tag>
</tags>
</entry>
<entry>
<title>Windows下Frpc安装与自启动</title>
<link href="//post/frpc-install-autostart.html"/>
<url>//post/frpc-install-autostart.html</url>
<content type="html"><![CDATA[<p>Windows下安装Frpc,并在windows的任务计划程序里设置Frpc自启动。</p><span id="more"></span><p>1、新建一个start.bat文件</p><pre class="line-numbers language-bash" data-language="bash"><code class="language-bash">@echo off:homefrpc -c frpc.inigoto home</code></pre><p>2、 打开<code>任务计划程序</code>(<code>cmd</code>-><code>taskschd.msc</code>)</p><p>3、安装步骤如下截图:</p><p><img src="http://file.uuxia.top:88/showdoc/img/frpc/install/frpc-install-autostart-001.png"></p><hr><p><img src="http://file.uuxia.top:88/showdoc/img/frpc/install/frpc-install-autostart-002.png"></p><hr><p><img src="http://file.uuxia.top:88/showdoc/img/frpc/install/frpc-install-autostart-003.png"></p><hr><p><img src="http://file.uuxia.top:88/showdoc/img/frpc/install/frpc-install-autostart-004.png"></p>]]></content>
<categories>
<category> frpc </category>
</categories>
<tags>
<tag> frpc </tag>
</tags>
</entry>
<entry>
<title>小米9刷 PixelExperience ROM教程</title>
<link href="//post/cepheus-lock-rom.html"/>
<url>//post/cepheus-lock-rom.html</url>
<content type="html"><![CDATA[<p>小米9刷入官方rom</p><span id="more"></span><h2 id="小米9解锁"><a href="#小米9解锁" class="headerlink" title="小米9解锁"></a>小米9解锁</h2><ol><li>确保手机插入了一张SIM卡,并登陆小米账号,并断开Wi-Fi连接;</li><li>开启<code>开发者调试模式</code>,<code>Settings</code> > <code>About Phone</code>, 连续点击 <code>MIUI Version</code> 5次;</li><li>绑定设备到小米账号,<code>Settings</code> > <code>Additional settings</code> > <code>Developer options</code> > <code>Mi Unlock status</code></li><li>下载<a href="http://file.uuxia.top:88/soft/mi9/miflash_unlock-en-6.5.224.28.zip">小米解锁程序</a>(仅支持windows),<a href="http://www.miui.com/unlock/index.html">官方解锁网站;</a></li><li>手动进入Bootloader模式(关机后,同时按住开机键和音量下键);</li><li>通过USB连接手机,点击 “解锁”按钮;</li><li>遇到电脑识别不了手机,需要安装驱动,可以使用<a href="https://xiaomirom.com/download-xiaomi-flash-tool-miflash/">小米刷机工具</a>自带驱动安装。</li></ol><h2 id="刷入-PixelExperience-Recovery"><a href="#刷入-PixelExperience-Recovery" class="headerlink" title="刷入 PixelExperience Recovery."></a>刷入 PixelExperience Recovery.</h2><ol><li>下载<a href="http://file.uuxia.top:88/soft/mi9/recovery_cepheus-12.1-20220611-0701-UNOFFICIAL.img">PixelExperience Recovery;</a></li><li>将小米9手机连接PC电脑,并运行一下指令进入bootloader模式:<pre class="line-numbers language-none"><code class="language-none">adb reboot bootloader</code></pre></li><li>查看手机是否连接成功:<pre class="line-numbers language-none"><code class="language-none">fastboot devices</code></pre></li><li>开始刷入<code>PixelExperience Recovery</code><pre class="line-numbers language-none"><code class="language-none">fastboot flash recovery recovery_cepheus-12.1-20220611-0701-UNOFFICIAL.img</code></pre></li></ol><h2 id="开始-PixelExperience-ROM-刷机"><a href="#开始-PixelExperience-ROM-刷机" class="headerlink" title="开始 PixelExperience ROM 刷机"></a>开始 PixelExperience ROM 刷机</h2><ol><li>uuxia编译的<a href="http://file.uuxia.top:88/soft/mi9/PixelExperience_cepheus-12.1-20220611-0701-UNOFFICIAL.zip">ROM包</a>下载</li><li>按 <code>Volume Up</code> + <code>Power</code>;</li><li>清空数据 <code>Format data / factory reset</code>;</li><li><code>Apply Update</code> > <code>Apply from ADB</code>;</li><li>PC电脑端执行 <code>adb sideload PixelExperience_cepheus-12.1-20220611-0701-UNOFFICIAL.zip</code></li></ol><h2 id="附小米9刷回官方ROM"><a href="#附小米9刷回官方ROM" class="headerlink" title="附小米9刷回官方ROM"></a><a href="https://wiki.pixelexperience.org/devices/cepheus/build/">附小米9刷回官方ROM</a></h2><p><video src="http://file.uuxia.top:88/movies/%E7%94%B5%E8%A7%86%E5%89%A7/%E5%87%A1%E4%BA%BA%E4%BF%AE%E4%BB%99%E4%BC%A0/%E5%87%A1%E4%BA%BA%E4%BF%AE%E4%BB%99%E4%BC%A0%E7%AC%AC%E4%B8%80%E8%BE%91%5B01-08%5D.mov" style="width: 100%; height: 100%;" controls="controls"></video></p>]]></content>
<categories>
<category> PixelExperience </category>
<category> 小米9 </category>
</categories>
<tags>
<tag> cepheus </tag>
<tag> PixelExperience </tag>
<tag> 刷机 </tag>
<tag> Recovery </tag>
</tags>
</entry>
<entry>
<title>Android 编译 openssl 的注意事项</title>
<link href="//post/opensslforandroid.html"/>
<url>//post/opensslforandroid.html</url>
<content type="html"><![CDATA[<span id="more"></span><p>以下载链接<a href="https://www.openssl.org/source/openssl-1.1.1o.tar.gz%E4%B8%BA%E4%BE%8B">https://www.openssl.org/source/openssl-1.1.1o.tar.gz为例</a><br><br>下载解压之后,查看根目录的 NOTES.ANDROID,其中有</p><pre class="line-numbers language-asm" data-language="asm"><code class="language-asm">export ANDROID_NDK_HOME=/home/whoever/Android/android-sdk/ndk/20.0.5594570PATH=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin:$ANDROID_NDK_HOME/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin:$PATH./Configure android-arm64 -D__ANDROID_API__=29make</code></pre><p>这里就是最直接的编译方式了。但是这样编译之后,会有一个坑<br></p><pre class="line-numbers language-asm" data-language="asm"><code class="language-asm">lrwxrwxrwx 1 ubuntu ubuntu 16 Jun 9 21:23 libcrypto.so -> libcrypto.so.1.1-rwxrwxr-x 1 ubuntu ubuntu 2754216 Jun 9 21:23 libcrypto.so.1.1lrwxrwxrwx 1 ubuntu ubuntu 13 Jun 9 21:23 libssl.so -> libssl.so.1.1-rwxrwxr-x 1 ubuntu ubuntu 596600 Jun 9 21:23 libssl.so.1.1</code></pre><p>编译时尝试链接 libssl.so ,实际上会链接到 libssl.so.1.1 ,但是当你尝试将 libssl.so.1.1 集成到 Android studio 工程内时,会发现 libssl.so.1.1 这种命名格式so,Android studio 是不会自动将其打包到 apk 内的,即使将 libssl.so.1.1 改名为 libssl.so 可以集成到 apk ,app运行时仍然会去找 libssl.so.1.1。因为 so 内部有其文件名信息</p><pre class="line-numbers language-asm" data-language="asm"><code class="language-asm">$objdump -p libssl.so | grep SONAME SONAME libssl.so.1.1</code></pre><p>对于Android来说,我们更希望,编译之后,so 本身名字就叫 libssl.so。<br>具体做法是解压 openssl-1.1.1o.tar.gz 之后,修改 15-android.conf<br>大概 193 行</p><pre class="line-numbers language-asm" data-language="asm"><code class="language-asm">my %targets = ( "android" => { inherit_from => [ "linux-generic32" ], template => 1, ################################################################ # Special note about -pie. The underlying reason is that # Lollipop refuses to run non-PIE. But what about older systems # and NDKs? -fPIC was never problem, so the only concern is -pie. # Older toolchains, e.g. r4, appear to handle it and binaries # turn out mostly functional. "Mostly" means that oldest # Androids, such as Froyo, fail to handle executable, but newer # systems are perfectly capable of executing binaries targeting # Froyo. Keep in mind that in the nutshell Android builds are # about JNI, i.e. shared libraries, not applications. cflags => add(sub { android_ndk()->{cflags} }), cppflags => add(sub { android_ndk()->{cppflags} }), cxxflags => add(sub { android_ndk()->{cflags} }), bn_ops => sub { android_ndk()->{bn_ops} }, bin_cflags => "-pie", enable => [ ], shared_extension => ".so", ### 这一行是新加的 }, </code></pre><p>这样可以编译出来不带版本后缀的 libssl.so 和 libcrypto.so</p><p>可以参考下边的懒人脚本来自行编译</p><pre class="line-numbers language-asm" data-language="asm"><code class="language-asm">#!/bin/bashfunction buildopenssl(){ androidarch=$1 toolchain=$2 if [ ! -f openssl-1.1.1o.tar.gz ]; then wget https://www.openssl.org/source/openssl-1.1.1o.tar.gz fi if [ !-d openssl-1.1.1o ]; then tar -xf openssl-1.1.1o.tar.gz fi if [ -z $ANDROID_NDK_HOME ]; then echo "missing ANDROID_NDK_HOME" exit fi pushd openssl-1.1.1o PATH=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin:$ANDROID_NDK_HOME/toolchains/${toolchain}-linux-androideabi-4.9/prebuilt/linux-x86_64/bin:$PATH ./Configure android-$androidarch -D__ANDROID_API__=26 make clean make popd}buildopenssl arm64 aarch64#buildopenssl arm arm#buildopenssl x86 x86#buildopenssl x86_64 x86_64</code></pre><p>使用时,将 NDK_HOME传入,例如,脚本保存为 build.sh,则执行命令</p><pre class="line-numbers language-asm" data-language="asm"><code class="language-asm">ANDROID_NDK_HOME=/home/whoever/android-ndk-r21e ./build_android_openssl.sh</code></pre><p>想为 Android (arm/x86/x86_64)编译时,修改脚本末尾的 buildopenssl 注释</p><p><a href="https://www.cnblogs.com/SupperMary/p/16361303.html?share_token=D86811DE-FA19-49BF-A4AB-B50D1D50C467&tt_from=copy_link&utm_source=copy_link&utm_medium=toutiao_ios&utm_campaign=client_share">友情链接</a></p>]]></content>
<categories>
<category> ndk </category>
<category> openssl </category>
</categories>
<tags>
<tag> ndk </tag>
<tag> Android </tag>
<tag> openssl </tag>
</tags>
</entry>
<entry>
<title>IoT接入文档</title>
<link href="//post/iot-used.html"/>
<url>//post/iot-used.html</url>
<content type="html"><![CDATA[<h1 id="4-3-设备与平台通信接口"><a href="#4-3-设备与平台通信接口" class="headerlink" title="4.3 设备与平台通信接口"></a>4.3 设备与平台通信接口</h1><h3 id="4-3-1-注册"><a href="#4-3-1-注册" class="headerlink" title="4.3.1 注册"></a>4.3.1 注册</h3><p>接口描述:设备上电联网后,检测本地是没有登录信息和注册标志,<br>设备需要到平台进行注册激活,注册地址固定 URL,且分为测试和正<br>式服务器地址(域名或 IP、端口)。<br>正式服务器地址(OPENHOST):open.clife.cn<br>测试服务器地址(TESTHOST):test.clife.cn<br>正式或者测试服务器请求 URL 只需要对服务器地址进行互换即可。</p><h4 id="4-3-1-1-请求"><a href="#4-3-1-1-请求" class="headerlink" title="4.3.1.1 请求"></a>4.3.1.1 请求</h4><p>请求 URL:http(s)://OPENHOST/device/register</p><p>请求参数:</p><ul><li><input checked="" disabled="" type="checkbox"> authLevel=安全认证级别(0 高级,1 中级,2 初级)</li><li><input checked="" disabled="" type="checkbox"> productCode=产品编码(初、中级认证级别必选)</li><li><input checked="" disabled="" type="checkbox"> devId=设备 ID 号(高级认证级别必选)</li></ul><p>请求头:Content-Type: application/json<br><br>请求类型:POST <br><br>请求方向:设备->平台<br></p><table><thead><tr><th>参数名</th><th align="center">类型</th><th align="left">类型</th><th align="center">描述</th></tr></thead><tbody><tr><td>cmd</td><td align="center">Number</td><td align="left">功能码,取值 2000</td><td align="center">Y</td></tr><tr><td>ver</td><td align="center">String</td><td align="left">通讯协议版本,通讯双方需要比对版本号,高版本向下兼容,格式示例:1.0</td><td align="center">Y</td></tr><tr><td>dir</td><td align="center">String</td><td align="left">传递方向,同 4.1.1.1</td><td align="center">Y</td></tr><tr><td>msgId</td><td align="center">Number</td><td align="left">帧序号,回复帧与请求帧中值相同,否则作为异常处理(丢包、错误)。帧序号由请求方管理,确保帧的唯一性,可做累加计算。</td><td align="center">Y</td></tr><tr><td>prio</td><td align="center">Number</td><td align="left">功能优先级,高优先级数据报文优先处理,默认中等优先级。优先级等级:<br>0:低优先级<br>1:中优先级<br>>=2:高优先级</td><td align="center">N</td></tr><tr><td>timestamp</td><td align="center">String</td><td align="left">时间戳,最小单位毫秒,UTC-8 时区。设备首次注册使用设备本地时间做时间戳,通过平台回复内容再同步时间戳。</td><td align="center">Y</td></tr><tr><td>data</td><td align="center">Object</td><td align="left">关键数据对象体,HTTP 请求时需要对此数据内容作加密并使用 base64 编码处理,加解密密钥需平台申请 devKey</td><td align="center">Y</td></tr><tr><td>productCode</td><td align="center">String</td><td align="left">data 中成员,产品编码,平台申请,初、中级认证必选</td><td align="center">N</td></tr><tr><td></td><td align="center"></td><td align="left"></td><td align="center"></td></tr></tbody></table><hr><h4 id="4-3-2-8-文件操作"><a href="#4-3-2-8-文件操作" class="headerlink" title="4.3.2.8 文件操作"></a>4.3.2.8 文件操作</h4><p>接口描述:平台通知设备下载文件,或者请求设备上传文件。<br>该接口主要分为升级、日志调试、收发文件三大功能。</p><h5 id="4-3-2-8-1-请求"><a href="#4-3-2-8-1-请求" class="headerlink" title="4.3.2.8.1 请求"></a>4.3.2.8.1 请求</h5><p>请求方向:平台->设备</p><table><thead><tr><th>参数名</th><th align="center">类型</th><th align="left">类型</th><th align="center">描述</th></tr></thead><tbody><tr><td>cmd</td><td align="center">Number</td><td align="left">功能码,取值 2000</td><td align="center">Y</td></tr><tr><td>ver</td><td align="center">String</td><td align="left">通讯协议版本,通讯双方需要比对版本号,高版本向下兼容,格式示例:1.0</td><td align="center">Y</td></tr><tr><td>dir</td><td align="center">String</td><td align="left">传递方向,同 4.1.1.1</td><td align="center">Y</td></tr><tr><td>msgId</td><td align="center">Number</td><td align="left">帧序号,回复帧与请求帧中值相同,否则作为异常处理(丢包、错误)。帧序号由请求方管理,确保帧的唯一性,可做累加计算。</td><td align="center">Y</td></tr><tr><td>prio</td><td align="center">Number</td><td align="left">功能优先级,高优先级数据报文优先处理,默认中等优先级。优先级等级:<br>0:低优先级<br>1:中优先级<br>>=2:高优先级</td><td align="center">N</td></tr><tr><td>timestamp</td><td align="center">String</td><td align="left">时间戳,最小单位毫秒,UTC-8 时区。设备首次注册使用设备本地时间做时间戳,通过平台回复内容再同步时间戳。</td><td align="center">Y</td></tr><tr><td>data</td><td align="center">Object</td><td align="left">关键数据对象体,HTTP 请求时需要对此数据内容作加密并使用 base64 编码处理,加解密密钥需平台申请 devKey</td><td align="center">Y</td></tr><tr><td>fileMode</td><td align="center">String</td><td align="left">data 中成员,文件操作模式,取值:<br>“DOWN”:下载模式<br>“UP”:上传模式<br>“QUERY”:查询文件信息(主要是版本号)</td><td align="center">Y</td></tr><tr><td>productVer</td><td align="center">Number</td><td align="left">data 中成员,产品版本(总版本号),基础版本从 1 开始,<strong>下载模式为升级时必选</strong></td><td align="center">N</td></tr><tr><td>fileInfo</td><td align="center">Array of Object</td><td align="left">data 中成员,文件信息列表,包括 Url、软硬件版本等</td><td align="center">Y</td></tr><tr><td>fileType</td><td align="center">String</td><td align="left">fileInfo 中成员,文件作用类型,取值:<br>1. 升级功能<br>“FIRM”: 设备升级固件,下载模式<br>“SUBFIRM”: 子设备(插件)的升级固件, 下载模式<br>“PROFILE”:设备 profile 文件<br>2. 日志调试<br>“LOG”:设备日志文件,上传模式<br>(3)文件收发<br>“PHOTO”:照片文件<br>“VIDEO”:视频文件<br>“VOICE”:音频文件 <br>“DATA”:记录数据文件</td><td align="center">Y</td></tr><tr><td>devNum</td><td align="center">Number</td><td align="left">fileInfo 内部成员,设备(插件)ID 号,当 “<strong>fileType</strong>”为“<strong>SUBFIRM</strong>”时必选</td><td align="center">N</td></tr><tr><td>software</td><td align="center">String</td><td align="left">fileInfo 内部成员,软件版本号,fileType 为 “<strong>FIRM</strong>”、“<strong>SUBFIRM</strong>”升级固件时必选</td><td align="center">N</td></tr><tr><td>hardware</td><td align="center">String</td><td align="left">fileInfo 内部成员,硬件版本号,fileType 为 “<strong>FIRM</strong>”、“<strong>SUBFIRM</strong>”升级固件时必选</td><td align="center">N</td></tr><tr><td>url</td><td align="center">String</td><td align="left">fileInfo 内部成员,下载或者上传文件的 Url文件地址</td><td align="center">Y</td></tr><tr><td>md5</td><td align="center">String</td><td align="left">fileInfo 内部成员,下载文件的 MD5 校验码,16 进制字符串格式,<strong>升级必选</strong></td><td align="center">N</td></tr><tr><td>checkSum</td><td align="center">Number</td><td align="left">fileInfo 内部成员,下载文件的累加和,<strong>升级必选</strong></td><td align="center">N</td></tr><tr><td>startTime</td><td align="center">Number</td><td align="left">data 中成员,文件操作相对当前系统时间的<br>开始时间偏移,单位秒,三种情况:<br><0:当前时间之前的时间点<br>0:当前时间点<br>>0:当前时间后的时间点</td><td align="center">N</td></tr><tr><td>stopTime</td><td align="center">Number</td><td align="left">data 中成员,文件操作相对当前系统时间的<br>结束时间偏移,单位秒,三种情况:<br><0:当前时间之前的时间点<br>0:当前时间点<br>>0:当前时间后的时间点<br>且满足 fileStopTime >= fileStartTime</td><td align="center">N</td></tr></tbody></table><p>示例:<br><br>文件下载模式:<br><br>加密前:<br></p><pre class="line-numbers language-asm" data-language="asm"><code class="language-asm">{ "cmd": 2019, "ver": "1.0", "dir": "30", "timestamp": 1617787651542, "msgId": 23454, "data": { "fileMode": "DOWN", "productVer": 2, "fileInfo": [ { "fileType": "FIRM", "devNum": 0, "software": "1.0.2.0", "hardware": "02", "checkSum": 34458424, "md5": "6d348c902ace4d09b6d62ce982dc8ace", "url": "http://clife.open.cn/device/ota/esp8266.bin" }, { "fileType": "SUBFIRM", " devNum": 1, "software": "01", "hardware": "02", "checkSum": 764234235, "md5": "6d348c902ace4d09b6d62ce982dc8ace", "url": "http://clife.open.cn/device/ota/esp8266_1.bin" } ], "startTime": 0, "stopTime": 600 }}</code></pre><p>文件上传模式:</p><pre class="line-numbers language-asm" data-language="asm"><code class="language-asm"> { "cmd": 2019, "ver": "1.0", "dir": "30", "timestamp": 1617787651542, "msgId": 231, "data": { "fileMode": "UP", "fileInfo": [ { "fileType": "PHOTO", "url": "http://clife.open.cn/device/storage" } ], "startTime": 0, "stopTime": 60 }}</code></pre><h5 id="4-3-2-8-2-响应"><a href="#4-3-2-8-2-响应" class="headerlink" title="4.3.2.8.2 响应"></a>4.3.2.8.2 响应</h5><p>用于升级回复、查询回复(升级后版本主动上报)或者主动升级查询。<br><br>请求方向:设备->平台<br></p><table><thead><tr><th>参数名</th><th align="center">类型</th><th align="left">类型</th><th align="center">描述</th></tr></thead><tbody><tr><td>cmd</td><td align="center">Number</td><td align="left">功能码,取值 2000</td><td align="center">Y</td></tr><tr><td>ver</td><td align="center">String</td><td align="left">通讯协议版本,通讯双方需要比对版本号,高版本向下兼容,格式示例:1.0</td><td align="center">Y</td></tr><tr><td>dir</td><td align="center">String</td><td align="left">传递方向,同 4.1.1.1</td><td align="center">Y</td></tr><tr><td>msgId</td><td align="center">Number</td><td align="left">帧序号,回复帧与请求帧中值相同,否则作为异常处理(丢包、错误)。帧序号由请求方管理,确保帧的唯一性,可做累加计算。</td><td align="center">Y</td></tr><tr><td>prio</td><td align="center">Number</td><td align="left">功能优先级,高优先级数据报文优先处理,默认中等优先级。优先级等级:<br>0:低优先级<br>1:中优先级<br>>=2:高优先级</td><td align="center">N</td></tr><tr><td>timestamp</td><td align="center">String</td><td align="left">时间戳,最小单位毫秒,UTC-8 时区。设备首次注册使用设备本地时间做时间戳,通过平台回复内容再同步时间戳。</td><td align="center">Y</td></tr><tr><td>data</td><td align="center">Object</td><td align="left">关键数据对象体,HTTP 请求时需要对此数据内容作加密并使用 base64 编码处理,加解密密钥需平台申请 devKey</td><td align="center">Y</td></tr><tr><td>respCode</td><td align="center">Number</td><td align="left">data 中成员,升级结果码,详见表 5.4-1</td><td align="center">Y</td></tr><tr><td>respCont</td><td align="center">String</td><td align="left">data 中成员,升级结果描述,详见表 5.4-1</td><td align="center">Y</td></tr><tr><td>productVer</td><td align="center">Number</td><td align="left">data 中成员,产品版本(总版本号),基础版本从 1 开始, <strong>respCode 为 3 是必选</strong></td><td align="center">N</td></tr><tr><td>devVer</td><td align="center">Array of Object</td><td align="left">data 中成员,设备版本,包括软件版本、硬件版本、设备编号, <strong>respCode 为 3 是必选</strong></td><td align="center">N</td></tr><tr><td>software</td><td align="center">String</td><td align="left">devVer 中成员,设备软件(固件)版本,格式“主版本.次版本.修订版本.修复版本”,如1.0.0.0,<strong>详见 5.1</strong></td><td align="center">N</td></tr><tr><td>hardware</td><td align="center">String</td><td align="left">devVer 中成员,设备硬件版本,格式“主版本.次版本”,如 1.0</td><td align="center">N</td></tr><tr><td>devNum</td><td align="center">Number</td><td align="left">devVer 中成员,设备编号,特别的,0 代表通信模组</td><td align="center">N</td></tr></tbody></table><p>示例:<br><br>文件升级(下载模式)回复:<br></p><pre class="line-numbers language-asm" data-language="asm"><code class="language-asm">{ "cmd": 2018, "ver": "1.0", "dir": "03", "timestamp": 1617787651542, "msgId": 23454, "data": { "respCode": 3, "respCont": "ver", "productVer": 2, "devVer": [ { "software": "1.0.0.0", "hardware": "1.0", "devNum": 0 }, { "software": "01", "hardware": "02", "devNum": 1 } ] }}</code></pre><p>主动升级查询:</p><pre class="line-numbers language-asm" data-language="asm"><code class="language-asm">{ "cmd": 2018, "ver": "1.0", "dir": "03", "timestamp": 1617787651542, "msgId": 23454, "data": { "respCode": 2, "respCont": "SUBFIRM" }}</code></pre><h2 id="5-1-版本号约定"><a href="#5-1-版本号约定" class="headerlink" title="5.1 版本号约定"></a>5.1 版本号约定</h2><p>格式:主版本.次版本.修订版本.修复版本<br><br>版本号变化说明如表 5.1-1:<br></p><table><thead><tr><th><strong>版本号</strong></th><th align="left"><strong>软件</strong></th><th align="center">硬件</th></tr></thead><tbody><tr><td>主版本</td><td align="left">软件兼容性变化时递增</td><td align="center">硬件大改动时递增</td></tr><tr><td>次版本</td><td align="left">软件增加新功能,不影响兼容性时递增</td><td align="center">硬件小改动时递增,非必需</td></tr><tr><td>修订版本</td><td align="left">BUG 修复时递增</td><td align="center">无</td></tr><tr><td>修订版本</td><td align="left">优化记录或者测试时递增,非必需</td><td align="center">无</td></tr></tbody></table><ul><li>表 5.1-1 版本号变化说明</li></ul><p>版本级别:主版本 > 次版本 > 修订版本 > 修复版本<br><br>当低一级别的版本号累计到 100 时,递增上一级版本,低一级版本号 归零。<br></p><h2 id="5-3-功能-ID"><a href="#5-3-功能-ID" class="headerlink" title="5.3 功能 ID"></a>5.3 功能 ID</h2><table><thead><tr><th><strong>版本号</strong></th><th align="left"><strong>说明</strong></th></tr></thead><tbody><tr><td>2000</td><td align="left">注册请求</td></tr><tr><td>2001</td><td align="left">注册响应</td></tr><tr><td>2004</td><td align="left">连接请求</td></tr><tr><td>2005</td><td align="left">连接响应</td></tr><tr><td>2006</td><td align="left">数据上报请求</td></tr><tr><td>2009</td><td align="left">数据查询请求</td></tr><tr><td>2011</td><td align="left">数据控制请求</td></tr><tr><td>2012</td><td align="left">解绑回复</td></tr><tr><td>2013</td><td align="left">设备解绑</td></tr><tr><td>2014</td><td align="left">遗嘱</td></tr><tr><td>2017</td><td align="left">强制下线</td></tr><tr><td>2018</td><td align="left">文件操作响应</td></tr><tr><td>2019</td><td align="left">文件操作请求</td></tr></tbody></table><ul><li>表 5.3-1 功能 ID 统计<br>说明:<br><br> 功能码在 2000 及以上范围表示设备与服务器使用的功能码;<br><br> 功能码 2000 以下范围属于本地通信使用,其中 1100 以下范围功 能码用作配网,1100 及以上范围用作设备与网关通信使用。<br></li></ul><h2 id="5-4-升级结果码"><a href="#5-4-升级结果码" class="headerlink" title="5.4 升级结果码"></a>5.4 升级结果码</h2><table><thead><tr><th><strong>响应码(respCode)</strong></th><th align="left"><strong>描述(respCont)</strong></th><th align="left"><strong>说明</strong></th></tr></thead><tbody><tr><td>0</td><td align="left">[1,100]</td><td align="left">升级进度信息:<br>1:版本下载完成,开始升级<br>100:升级完成</td></tr><tr><td>1</td><td align="left">[1,100]</td><td align="left">下载进度信息:<br>1:开始下载<br>100:完成下载</td></tr><tr><td>2</td><td align="left">[ALL,FIRM,SUBFIRM]</td><td align="left">设备主动请求升级:<br>ALL:设备所有升级固件(默认)<br>FIRM: 设备升级固件新版本请求<br>SUBFIRM: 子设备(插件)的升级固<br>件新版本请求</td></tr><tr><td>3</td><td align="left">描述信息</td><td align="left">查询响应信息:<br>服务器查询时回复</td></tr><tr><td>-1</td><td align="left">[0,1,2,X]</td><td align="left">过程异常信息:<br>0:URL非法或设备忙;<br>1:升级中断;<br>2:版本下载完成,校验异常取消升级;<br>X:其他异常信息(可为具体描述)</td></tr></tbody></table><ul><li>表 5.4-1 升级结果码表<br></li></ul><p>具体为:<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;正常升级:{1,1},{1,100},{0,1},{0,100}上报至少 4 个事件<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;升级异常:{-1,0};{-1,1};{-1,2}上报三种情况之一的若干事件<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;主动(重新)请求升级:{2,FIRM} 或者 {2,SUBFIRM}<br></p>]]></content>
<categories>
<category> IoT </category>
<category> mqtt </category>
</categories>
<tags>
<tag> Iot </tag>
<tag> mqtt </tag>
<tag> c++ </tag>
</tags>
</entry>
<entry>
<title>SSH公钥免密登录</title>
<link href="//post/ssh-pub-login.html"/>
<url>//post/ssh-pub-login.html</url>
<content type="html"><![CDATA[<div class="hbe hbe-container" id="hexo-blog-encrypt" data-wpm="Oh, this is an invalid password. Check and try again, please." data-whm="OOPS, these decrypted content may changed, but you can still have a look."> <script id="hbeData" type="hbeData" data-hmacdigest="002fc0284bc617957e4e5cb3f87737573736ed12075d9ca5275bee9e22872dc6">8a45f6bad0c5eda31f44591d6b22cf7530ba935aee346f7f54f7102558f92ebfafb20dbdf81dbe2f773964475504fb1082d31a690047a004c22e4f335858dfb5361dc1d31dd4e158f0aed085ec5f603ddff66ebf60427c76db8167c131743779960b899cfd6429ba14b4d90b99f5d42b33cb71d4a4c2a99db95065e1885d3740fd20c113ed7c0c0e98323daae0cfd7f02f3dbff07059e9d2e77e58f893e15912e7070794bf28615898c125b278f49479bb847f36f912a0d9b7cd1bc3705fb4decb8cfd2ee238ce9985404449f8adf78022217152da69a042ca12c4df55f6fe826ee6471590edfb738003c25751c2cb9770b3eb28a505238a7bd600e0c2ae07b86dd79ff1c163c1e66359fb8f23e3601e5ae029064cd743f3de8632f062ad5e2f81b02ac4ec673d22ed9d92828eaa139bea1c8d1b2b67c3902476bdff5607ee7cf75aadd32704bdb66d3be04b7c5bed63e9989884ac6ed09cf93b55ad2cabeadeee75bf89701061337a44169517c4b8bf64e2ec798cabbb9aee93c4a6619bef1e73ae51e34008028ce083fde826dfb75baa6198c76eddc2120462a421a6d0d75655793fb5936b1ba92c00cf382bf1a7708d5d64ac323f75175ad03e4d5a1a45925feb927680b7d842fdc501ccc196ff08309f9da7d554c796148e3ffe539bc1a77cf0afbac4fdad25a92d5ee02549899a88890d54494d69a17c3c7a636ac3596a6df67c2f50f7058e0522b1a5e9f1228afe1a87db496e1cac63faf057113d39accf0334051ddea0b492086f90b4302b4f1365c4c4dea4823f9eecd4f366730694e714f1daa2c254a4b56d2df0d7ef0bfb8885599de6c86240799f8bd17527b68bba49688a34ebd53a35d04998db273432e76da6a4c224bc27b0f58b320042dfda81aa288ea198a21d1a72314f8621681738d7476992945fcf897a8e973f10f050f2f624166655c1faf8a929c29c8e806ae6d76a60489b446a607bb496fe0777d8f175ee8de06718df5c77748fb3af097adda251f0cf7ac85244f2d55663ae31998459add2616f06a02c39a74c0a124f4486477578c33c84ca48bb13a7135b4209939ede3e024ee36cdafc6423bd1d06f1f9d7b5bc739537533ebbddc4243a1090c63d21d37b7aa98271419cae3d1f2770407c5d7c083159eab1f191b1347997110ec7eed13d46f1b3b65f1551a642e6d2988d957c50c107989d1f0c27e7e32fa08695426f28103bd43287e0e023914b37f819e118e5b7b714d00cc99a203c3fab9f06aab148b0d838a67352ab040524ac724dff4e0e6c5aaed3c1c33528d1291a0f9b95b8c915a54031828d222fb53262008e9ab18f300a4a8e9dce194c54ef3007cf1dde623716edd8daf734ae0d6b3b1a16adafc3f7d78f73c9fdff955c49d8b7a281f741f63eb85b325b04ca942bb3f992ce07bf99cfbd797a3ca3e946ad8937eb76eccabefa14cba83e68ccac7a76a991c76464a5c9e61373b82b6ce5e918fb58ccd2e8e51c26ced5f55ebc4a41a6c6bab1af829a9e11572662acd9217b78e625d6eef760d21873c28034a2f1b044cfe8f0885251924c887d21088f512a37ffb34d11ee76ba53da380f965e502c07997aa9586c45ff9e7261670984a113ac239fe43473e70cbb24b3a8a0afd4c039a05389032732825a4d578743cf68587fd56f14bf87164afdad94929405eda5a1317d8d9ba6a02bace67f7f2b1dab9a5260faafe802b6ea54fe63370b5a8c6b2006b5115d092fd4375d7d836820e334d48e4775712ba75dc49692959a660b90e2b1f4e9f8e5161efe63b0b6cbe8c3ebdd661d287e733fb1a6c8bae7d68fffeebb6502d3d3ddc72e0fc02ba756264ab778be90d6c7b17accdcec0d4f32fa8d668c6a624546e11865758c39bfd59466818ad8c93bcb31518998c8b5ec9d175c8f8d01be4a218a27214a427ac8f98f14c50bfa366af240f0feb076d54d5c9be778379a6f7cf0c355e38fc6bb9d11af50a9c56b74e74549fbef080665373be2c702aba9bf380529cea4ee01b3e837bcd3ba247dd5f5a8c2a1fe2569bf62a3e725a6716f6009b37d70457a62602f54de68b5eda6915ad9c7cc46f7f0b3db9d135239d0282f553c01b5c2f1e91af6b1a46f30ef84977e745e31260a8ce8986d487afcabba91f2b65e8aa6f30a4bdb9a6cc24b74e9b31c4ce739fd3c9b7a1075b34fa9c35dec6a6b0a50a7503a87a24e8cc41c8b3bdd0f796f69640a1942b6e99cbf46a6b6991b59a32ef92dd38a3b905e531faaed3aac019f95adc730b3262f0f34545aa152c1eca387e4b8b824cda272fa9b065d4cf4dee4b650b40162dd9f373011442de9ad6779a23f0866b3f40e1e70183e0f3a8f39390c171b55316eb3de675ce19dcd5d6aaf846f02b238504a94a2c75cef4469be93a0a82eb9adaba7660f39f0cfb39a771978c9dc6721f1833accb0a8b91ef3930f60539cdbd7ae9515c321abb075a793c9409de0acae21c3771cb4396d8864eeb14378fdda7471542b8b7ce150e85821771b85522e939acb2a4b43a1950384c94ae02efb50aee584dc67c4a9549e9d2771421e6ae7f2d5252b631cdee0b0b948d8ac1ad4f908f1a2e401e43f549a41168f17d517f902763d2b2a87d858a17759665f62b70b792e3bcc2cd6a76bc4012b70e0f923b52273822cc7b271e29aec38a593a0043297c7097e5570e51d91f27eb66b1bde1eb6b92fdf17877ac9057870dae8fea285ac5f1bb972ff02f578cc5a7eaaf752ebb3f39ae647f25d652279e5f5465bd94bd9d3c92dfed6022482976f09d557a77328882062faa763eb092ffc06fc741db3cc3e99ff425415b768304aa7c53c7b5dcce43905621156a4b79f339e58a41658763ca81dd22bef1829282330616a8b64d0c7101045cf5de4367cca5ddaba0e01d129adcc97b44fd72b04ddab6b5645274652bf818b92f21f8279d41a9084cbb48b925c2fbbc5e45e05cbd122f2302ac2cf891b671148b4c591867eb10df45f3a7e0ec71fab24a23cc8d927da87cb971956d95ec8d5e857b3021e74a82e27d75d525eda4f3bc8abcca9784c59366f47f6df558edeb59946cba819fb487a10833b12111bce1814630e137c46207ec8aadf230f950538ffa9da7ad8bd58610651ea017ac7a289aeb51532fba79380fa15945340561bdd5e3b5d29d8a90d11cb6062a4f57f92ac09ef1935a31cf838b508b9b11fc1ead8da8ad529043332738e06a08715f5abfad18583393ea79dbec872f0b0a390e63e489ebd9caffcf368ded06e32165d7ba5907a6e208c4dde0a0dd347422edd178f7fd45fa85bb7ccf2bd9b82623c154f065e9a1ecf09ebc62c26baf9a58699ee86a8b523516c45da1bce7cff4803c5723d797498da5dd36becdbe57efaa42e222198820f5f603db8916f4399693a34226a6e08b1d5e15b2269fafa1edd0e4741337b939cfad5332e9732543caf7a50c484cfd179175ca62007e8ef11002c4b4a4278def974852d2edb421152ae837c08c6a686e2956175cf4f1a18119030eb01ba0f59835565b80c0741149fe97570e43de23eb16062a2838476bcec8979c035841f3e6fe05c127300f88ab356403a28edced3598aa713154168c2fee2ba2ece96689e482ca24287e4f6821c9e0b14a1dcb86cdbc0827f77fe639f807b1034fa8e309f1e6aa7c3a166d8376957efa1b85b43cb05e75175cbc8961705689d5f4e3b7ad7e4e67a29c0012755d09a5617893a120d1157ba3567210dd48fc62817d6d763944ba5ec8b94f2262098db35246afa5546f2676021613697a6c8f2ebde502b3dc1891e98994adb62e7a57d48d0d47726f3dba45db9756de5fa2aa668258a4ac5cc17bf74eaab420edd2dbac0f32bee46e72a6de51514a79f21de43dfc5dd77026c2bcc70c9ea63d5b8d42a73087662d0a40563bac7e63df96df83cbf75b16a4742f4a10c944619d865ad986a36edc567e578f4c097d9777a1d382f3497e7889295145c06e4847b15b680ac2e74251d2a018edb7279376284df64082eee5953931e84f4996a23d005c64af96a38dc0409e2032f3fdf26a6c03556ef0078fb4839e0c9fb3b7d69e3f54c9d54c3d3c36c798425af2b2f2ed30d40ebae8f76258b9be4354d73e192eec32f1d4bb82933b34828a66bd6720a874c21ed680c4fdd1a9a3ef28e63ed8f287d48b96ffabafb79250c3b09e9a198e6492f2b6db0b40ef15649d59bbbb68d8f4b6b461f3f5e32254f4d89e3b5c0ad1f0fe0b7faaa9bef199cc9267de5ca49185c398920185929b8cd911e17149fa970d4792d6ae3dec82962edd29aef35b61820b59b50f9f2aa92fd971e2c9a6b4098016135fe5910241792e3f282e226351e2cc6507bf032293a31713f7690ff6401ae1cbc1b0d660ba5a1bed37207c19b38b4442da566461ff67dc1336b3c48557706d1f97787a9e1011683b2bc491a7035e525a1300e1e3c95abc2fe041e47bd64eb9c350caf92644796ee78a4192544b37e3957855772e049e3f7892a590ab416b081621b318327a567cebe69dc849e22cd08c05cf9876c92450a1af611e2e35f0e8101f79b4c4f7b7373b58bd2eb9c349a7b32afac9f8f3355c38ea8aaf6b383bf7ac583961316e773bbb6df5a43c1876c0518c85bfbbab3c4592cb678ab3136801295ac32eedd5a946436af819b6a61226a88fd086ba3554526398bab6c4c9681f930759d7f7a3519607252c8bd585be8f4868978c8fd3acb9b1e62a3f6a49a61b75825d73ea85be14bf4626cff28d27c0a6b97a98d8ff1a8250e08a89e02f0d63a0460401d93f0f5679086a7c3cb6b05e4632e8c9f8b5126fcada75a19cbf2b14b1dd19c9cca2563b92565da79d0b9243f834621c2035ead4721e6318cd2d398a9ded023c38422cd855d6f73319286c43b032b8bdce4a2bcfe04469cb49622e9575556ccd4b911674905aa6a043062176624a27f75560c5956a97f6bfc954341896b9105ae294ea0bff56c10f0bf80f64f10f634aa66380e5056aa08e3420525d4d97b72305806ecf9df2976bdce5bb8bf1cda8cda16fad1c778662df07974bd454f7f7450e50b0691ba808b4561a01f08b4dffa5545b7a916bf5e2229da8fa89d54839cae9181f6355b6b68bb42d792e334957d2f266ef11fbefe6549c7bfd6f668f47f6adf3770c219b6ba46d1b7707ce1c37dc476299fd4ee997a423f29290d5debe1d2158ac37a11105b19532d5c7cb368ab7f9946a4962592c2e5bca8b84f8c51acf335955ce12cab536f752ef75b6a010919a27c51148c54edb37b23872f37c06ad279b66fcc0533f6d4bef214fb84eb128d13102ad74ac92d507a5e6236c841e11c9139cd8e0faad93ad4c7e9215f446ebe05aaf4cb288e08aaef76960827ef8b2cf4bce621d8e03871a68038e76c5a37edf7de93d1a35d7a5a0c53db39d77890025aee47cb3b095cc9b3607050d3628382a4cdd19f4c0e0c7fd9a7e75a7f9f8644662d2ea4925cd7a134632c95a9a5a729f6b22cecf6d153649515f1e6cc784590a47dafa95431bbde7b9dbc0f4eb1ae2f12e53c56027f4672e9e120d8d33dc947c6aef0ec26b056d2b59254dd275b9eb2d654ba40c60aea747bb8d3bd4e4b3d45c77695f23f8912bfb3b2d46ab517ad9d7092e94ff5452c107db7953e9401675c169318dd4f83ae37ef58da396c9cc01960b3ed99381d1c4e16a213a8239069c39c8a57cc05f923b9e74202f9fc05cc3510a4f360c5ed9f851239001f2f60e7f54a27da9a0f940cf27428823f5aa7bdd5cea59b88e11292beaa6fcec25cb55352d966cb0b450ee38aea1cf75ae2072a15827233ebd516b2575adb9561f6a2fd5d505884d9fd591f354513b60d6a1f0f97c1f712c011abc9791906169c83dfd4f8c5e9e187c12150e60bb1366e1fcaec1b64b5082b9dfa89d157d9efaa733e68f58b30586e1a8548eadc25116e687247ed41fb518b16f2100b3b15fa80db6ddfb05271378fc2143f48d8a1403a3cb1ff68887b5cb6b75bde9845e584731d28f7bbc7f5a2f8f17a0651236ac7b046065ea1b69cb1915a286b05ce53d245c8ec0e8dcf22c694fe6d6d3f07d87bc9eed3dba1903f42b98539700ae191d400d7805fd524590af640e55b35a9e0cb11148585894c7e6a2f8576bf0be87ad84299a1335926a02761ac37f6c8d0927ff59db60d53200cae13d26805e89c28294d73ceeb932f40c8b4ee5aef18ec2d1a657a8654f02279a26d73e01ca3b2b5ac6a2afa69ab030fe18163998a884dadaecbf9d9d87bafc0e8de77e85bb42fde28975ad59a5768af6aa311398f5e82c44a053fbdfb516e1b6b2ad1c9e1c0db106cd650fa5ae74eca867dd4255510bf64def1c5c63fcf537001b68d54b5eb123c0d9a340ec7ef5d839757a7d71c3da1dcd4f0e9bcf0f6688067b78a4ee9574cd29cc8452676b058af1962ceee867c7131c310a9d9f5bbaca27e93285d6a28695b95906abbcc670ca83ebb609529fdb1a313c7249ee8ceb5cd3f8e33c5fc062acf11eda4bf63f1253741d12c25356336512e5337e7cecfa7ab6db3a42cb0275710d0a77eae71931934ed4b8ab53d06b3cd99a0bf317118151770d44f58a3f9c1fefca3472e03bce744e64ab71137c87dfdf181898a5a10d8add93d7a78529b39dd2681161193a8ab1fa949bdad3d1b4ef246067d03578b1332675c22ef3c5e3b23757eb07f990cc5a60159dc1edb03d0410aa9efaac245624f0faf9541efbafac76a9ab38a57b5e556b00fb48ea5fce225ad776f4c5886bde3e123246aa15c9e743729b522427602ff2713</script> <div class="hbe hbe-content"> <div class="hbe hbe-input hbe-input-default"> <input class="hbe hbe-input-field hbe-input-field-default" type="password" id="hbePass"> <label class="hbe hbe-input-label hbe-input-label-default" for="hbePass"> <span class="hbe hbe-input-label-content hbe-input-label-content-default">Hey, password is required here.</span> </label> </div> </div></div><script data-pjax src="/lib/hbe.js"></script><link href="/css/hbe.style.css" rel="stylesheet" type="text/css">]]></content>
<categories>
<category> ssh </category>
</categories>
<tags>
<tag> ssh </tag>
<tag> pubkey </tag>
<tag> shell </tag>
</tags>
</entry>
<entry>
<title>ADB保存Android日志</title>
<link href="//post/logcat.html"/>
<url>//post/logcat.html</url>
<content type="html"><![CDATA[<p>Macos、Windows、linux下如何使用adb保存android手机的日志</p><span id="more"></span><h2 id="一、MacOsX、Linux下使用adb保存Android日志"><a href="#一、MacOsX、Linux下使用adb保存Android日志" class="headerlink" title="一、MacOsX、Linux下使用adb保存Android日志"></a>一、MacOsX、Linux下使用adb保存Android日志</h2><pre class="line-numbers language-bash" data-language="bash"><code class="language-bash">adb logcat -c && adb logcat -v time | grep "abss" > /Users/uuxia/Desktop/android.log</code></pre><h2 id="一、Windows下使用adb保存Android日志"><a href="#一、Windows下使用adb保存Android日志" class="headerlink" title="一、Windows下使用adb保存Android日志"></a>一、Windows下使用adb保存Android日志</h2><pre class="line-numbers language-bash" data-language="bash"><code class="language-bash">adb logcat -c && adb logcat -v time | find "abss" > D:/android.log</code></pre>]]></content>
<categories>
<category> android </category>
<category> logcat </category>
</categories>
<tags>
<tag> android </tag>
<tag> logcat </tag>
<tag> adb </tag>
</tags>
</entry>
<entry>
<title>基于Linux(centos/ubuntu)搭建树莓派C/C++程序编译环境</title>
<link href="//post/raspberry-build-env.html"/>
<url>//post/raspberry-build-env.html</url>
<content type="html"><![CDATA[<p>记录在Linux系统下搭建树莓派C/C++程序环境搭建的过程。</p><span id="more"></span><h2 id="一、安装gcc-x2F-g"><a href="#一、安装gcc-x2F-g" class="headerlink" title="一、安装gcc/g++"></a>一、安装gcc/g++</h2><pre class="line-numbers language-bash" data-language="bash"><code class="language-bash">yum install gcc-c++</code></pre><h2 id="二、-安装CMake"><a href="#二、-安装CMake" class="headerlink" title="二、 安装CMake"></a>二、 安装CMake</h2><ol><li>下载文件到本地:<pre class="line-numbers language-bash" data-language="bash"><code class="language-bash">wget https://github.com/Kitware/CMake/releases/download/v3.13.4/cmake-3.13.4.tar.gztar -xzvf cmake-3.13.4.tar.gzcd cmake-3.13.4/</code></pre></li><li>逐个运行:<pre class="line-numbers language-bash" data-language="bash"><code class="language-bash">./bootstrapmakesudo make install</code></pre></li></ol><h2 id="三、下载交叉编译工具"><a href="#三、下载交叉编译工具" class="headerlink" title="三、下载交叉编译工具"></a>三、下载交叉编译工具</h2><p><a href="https://developer.arm.com/downloads/-/gnu-a">https://developer.arm.com/downloads/-/gnu-a</a></p><pre class="line-numbers language-bash" data-language="bash"><code class="language-bash">wget https://armkeil.blob.core.windows.net/developer/Files/downloads/gnu-a/10.2-2020.11/binrel/gcc-arm-10.2-2020.11-x86_64-aarch64-none-linux-gnu.tar.xz</code></pre><p>解压:xz -d gcc-arm-10.2-2020.11-x86_64-aarch64-none-linux-gnu.tar.xz<br>解压:tar -xf gcc-arm-10.2-2020.11-x86_64-aarch64-none-linux-gnu.tar.xz</p>]]></content>
<categories>
<category> C/C++ </category>
<category> 树莓派 </category>
</categories>
<tags>
<tag> linux </tag>
<tag> C/C++ </tag>
<tag> 树莓派 </tag>
</tags>
</entry>
<entry>
<title>小米9基于PixelExperience源码编译步骤</title>
<link href="//post/cepheus.html"/>
<url>//post/cepheus.html</url>
<content type="html"><![CDATA[<h1 id="Pixel-Experience"><a href="#Pixel-Experience" class="headerlink" title="Pixel Experience"></a>Pixel Experience</h1><h3 id="Sync"><a href="#Sync" class="headerlink" title="Sync"></a>Sync</h3><pre class="line-numbers language-bash" data-language="bash"><code class="language-bash"># Initialize local repositoryrepo init -u https://github.com/PixelExperience/manifest -b twelve# Syncrepo sync -c -j$(nproc --all) --force-sync --no-clone-bundle --no-tags</code></pre><h3 id="Build"><a href="#Build" class="headerlink" title="Build"></a>Build</h3><pre class="line-numbers language-bash" data-language="bash"><code class="language-bash"># Set up environment$ . build/envsetup.sh# Choose a target$ lunch aosp_cepheus-userdebug$ lunch aosp_cepheus-user# Build the code$ mka bacon -j4</code></pre><h3 id="Turn-on-caching-to-speed-up-build"><a href="#Turn-on-caching-to-speed-up-build" class="headerlink" title="Turn on caching to speed up build"></a>Turn on caching to speed up build</h3><p>Make use of ccache if you want to speed up subsequent builds by running:</p><pre class="line-numbers language-none"><code class="language-none">export USE_CCACHE=1export CCACHE_EXEC=/usr/bin/ccache</code></pre><p>and adding that line to your ~/.bashrc file. Then, specify the maximum amount of disk space you want ccache to use by typing this:</p><pre class="line-numbers language-none"><code class="language-none">ccache -M 50G</code></pre><p>where 50G corresponds to 50GB of cache. This needs to be run once. Anywhere from 25GB-100GB will result in very noticeably increased build speeds (for instance, a typical 1hr build time can be reduced to 20min). If you’re only building for one device, 25GB-50GB is fine. If you plan to build for several devices that do not share the same kernel source, aim for 75GB-100GB. This space will be permanently occupied on your drive, so take this into consideration.</p><p>You can also enable the optional ccache compression. While this may involve a slight performance slowdown, it increases the number of files that fit in the cache. To enable it, run:</p><pre class="line-numbers language-none"><code class="language-none">ccache -o compression=true</code></pre><h3 id="Start-the-build"><a href="#Start-the-build" class="headerlink" title="Start the build"></a>Start the build</h3><p>Time to start building! Now, type:</p><pre class="line-numbers language-none"><code class="language-none">crootmka bacon -j$(nproc --all)</code></pre><h3 id="Install-the-build"><a href="#Install-the-build" class="headerlink" title="Install the build"></a>Install the build</h3><p>Assuming the build completed without errors (it will be obvious when it finishes), type the following in the terminal window the build ran in:</p><pre class="line-numbers language-none"><code class="language-none">cd $OUT</code></pre><p>There you’ll find all the files that were created. The two files of more interest are:</p><p>recovery.img, which is the PixelExperience recovery image.</p><p>A zip file whose name starts with ‘PixelExperience_’, which is the PixelExperience installer package.</p><p>Success! So… what’s next?<br>You’ve done it! Welcome to the elite club of self-builders. You’ve built your operating system from scratch, from the ground up. You are the master/mistress of your domain… and hopefully you’ve learned a bit on the way and had some fun too.</p><h3 id="Submitting-Patches"><a href="#Submitting-Patches" class="headerlink" title="Submitting Patches"></a>Submitting Patches</h3><p>Patches are always welcome! Please submit your patches to our Gerrit.</p><p><a href="https://wiki.pixelexperience.org/help/submit-patch/">Gerrit push guide</a></p><pre class="line-numbers language-none"><code class="language-none">unzip platform-tools-latest-linux.zip -d ~# Now you have to add adb and fastboot to your PATH. Open ~/.profile and add the following:# add Android SDK platform tools to pathif [ -d "$HOME/platform-tools" ] ; then PATH="$HOME/platform-tools:$PATH"ficurl https://storage.googleapis.com/git-repo-downloads/repo > /root/code/twelve/repochmod a+x /root/code/twelve/repocurl https://storage.googleapis.com/git-repo-downloads/repo > /media/psf/aosp/twelve/repochmod a+x /media/psf/aosp/twelve/repo./repo init -u https://github.com/PixelExperience/manifest -b twelverepo init -u https://github.com/PixelExperience/manifest -b twelvegit config --global user.email "[email protected]"git config --global user.name "uuxia"./repo sync -c -j$(nproc --all) --force-sync --no-clone-bundle --no-tags# Running configuration script:cd ~/git clone https://github.com/akhilnarang/scriptscd scripts./setup/android_build_env.sh./repo sync -c -j$(nproc --all) --force-sync --no-clone-bundle --no-tagssource build/envsetup.shlunch aosp_cepheus-userdebugexport USE_CCACHE=1export CCACHE_EXEC=/usr/bin/ccache# and adding that line to your ~/.bashrc file. Then, specify the maximum amount of disk space you want ccache to use by typing this:ccache -M 50Gccache -o compression=truecrootmka bacon -j$(nproc --all)export http_proxy=http://127.0.0.1:1087export https_proxy=http://127.0.0.1:1087git config --global http.proxy http://127.0.0.1:1087git config --global https.proxy http://127.0.0.1:1087git config --global core.gitproxy http://127.0.0.1:1087export http_proxy=http://127.0.0.1:1080export https_proxy=http://127.0.0.1:1080git config --global http.proxy http://127.0.0.1:1080git config --global https.proxy http://127.0.0.1:1080git config --global core.gitproxy http://127.0.0.1:1080git config --global --get http.proxygit config --global --get https.proxygit config --global --get core.gitproxygit config --global --unset http.proxygit config --global --unset https.proxygit config --global --unset core.gitproxyhttps://mirrors.tuna.tsinghua.edu.cn/git/AOSP/https://android.googlesource.comsudo chown -R root:root /root/cepheus</code></pre>]]></content>
<categories>
<category> AOSP </category>
<category> 小米9 </category>
</categories>
<tags>
<tag> cepheus </tag>
<tag> proxy </tag>
<tag> android </tag>
</tags>
</entry>
<entry>
<title>terminal代理设置</title>
<link href="//post/proxysetting.html"/>
<url>//post/proxysetting.html</url>
<content type="html"><![CDATA[<div class="hbe hbe-container" id="hexo-blog-encrypt" data-wpm="Oh, this is an invalid password. Check and try again, please." data-whm="OOPS, these decrypted content may changed, but you can still have a look."> <script id="hbeData" type="hbeData" data-hmacdigest="dbf4e0e8e07d33e53dc74eac7968851f1b52e9923e42cab7487caae535ab06af">8a45f6bad0c5eda31f44591d6b22cf7588611db6740aaf37b60e55b90bec518bc1eb700345aa787c7ef1afa6c70569b4348629e0544655146d9e90c01e723f592670b5c271f39b6511a9c2009c109c1f5d18f635ccac9809f1d05865f1c94098b76760725799024d2c6d60baa67ac82df75cbe5e53c5bdae97e78206f35ffdef9324c52b0db9903910efde62de86be7dd64a5b713f7a76b635330b63d74aa1b9b03d52ce395e2f8895e88f7b2907c5fc6f3046462bca019209ba9deb008918c0656fc6d7595900cca65411bf32939be478454729bcc1bcbd0aade6394dd74a94d7be4e1d8e7df6520fb72f8d896448358a2d18125c9897acba6482255393ceaf7a5742db96fd95d57e33a337bcaab5bed261d42f6eb45279ffb4dca557d350de116cace0e229797fdd1126889456ea75a4aa575edfbbdc1056d96d11bfe9ffe609bedf2f66ab5b668c3b3e4d49333aab458532b24b2ee40f5e45dbd9a75b1605455f1273fc4415d011bbad0c5c42785d2184fc06ce9221392f7bd7558d86d909d4b47e1f7cda1df9ccf83befa5d91c62632cd156e42e9377ec6dcf706663431739f669e5a172531e24eb343d963732ddd621dba8a33f56c241c3a67bce97f24ec2347e6f1fd826ef67202a90c773288f76d2027ddd25a9220097da56723e2271207033d08ec99ec5a1db8cddbd5a16df5802c01a03d31b2bb08f04709df5391d1611c37ff28a8252761756c956683ebc9fa33d9ca2a718e7e3fa4029e4dbf9f6eaeb564b92807188b8bfb67c305138e486744cacc988accfc9af1cd7dd757a417b6ad62990f96a4ef3e095ab16e55898d8a1eab26b741ec027f2860cdbdf53b3e0884db469d69ab6c4fdb14022a5d4bde8f6578374492e46296165275415f7945ac71d04a7dd5984508cae83e050f1ebd45bbc7bd5709ae61aadf0b48104ce81b23e5dfe6e30a6857341b6594e3e7bc0051116ebea5fa18ba2f3740cf424b8c2987551c0854480ca49ac50557c86bfdc6f90810dd54d2c356d7738a71363e264364228d43c0bcc300d66f5c042bea2b3e55c315571f2090f4cd2c59cadb1202dba29726087687b2c4d00be247c0f327072c7d1f53490dec8a59d93fd3c08508d9333b69c35dffbe80f62abc70afe5cf13871eccb7817c3991b1ddb482a952bf9b7e0bfefc7852da27eeda7d5386c5fcded053118aa3a7061391d454b46a5f941d54da0fa79b9d5f48665cabc4aae6a407f73da4e6fe4846e959e70a9075b58ba44df62c2fc4da43158ae5dad1ec83f241bbc33d3ee00ef456565a489f396e7e4dacc81914ed375c802bc80e2098bc278ff161019415b5a8815d0bae9265fce396924c9f3ab7ebe226e6d19716a134adfc03eca1f0dc365d77e6474198446b607df6f6871215a4ba296df576143006ed4822452f000247271f54dfeefa5ec79943974500ee9d150ee7b9fe742d6a5379e212c68e4de9651de1399ee59150c40de32094580b267abe8fc26e99568513cbc9c91945b7765255056e3026c568c340dd95e0b2615451bb601b01d7e179c5b9c0d5c0ff52c0d6347a61ee2f377d7322352a63396855ab78d1d5fa924ddf415d0e21297e13bbe22b10d1acd1bef06290b71669b6d81c4aa14b35ed63f444b67239da773e8f303bdd4895814c67118cc938902eced920af854daf8170e719f5b92deee26f545f0f8beead4b313b930fb5920f2e9211e4651bdd2d42ed2cc570ade3db6f3653e3b6f4af63444b534ad8a8f79359f2d36fcadabcd1de82e6d354f49bcb53f08183d5d34de04c2313171acc6579369ab598ed7078b86725519132e0af352eb5abc8fd8404b1451d8b9461e534631d5da0cae7a1656eda9ef6f3af14f072524bf98583b0dcc93671fcf2d80e2285b70b9a6def508b0ca9b95c49ee24b64141ee78135d4c4a74ffe78f1238a8082cad2f69b576cc9b49da303447a4dc1c4a8b71779a6f51437864e0fce56278fc98ac9860554e0974bd0b787263da036075b473e48a03dc58c9fc539e7bb8e8d5c35c4cb976cef217f69992e74bda3c06d0b2b498a950e9a2976933313eca130745e353694debc5c380073834725753046883539f2645261d5e6189fda72923cdc752e9e840a3881ad8bc5e2408ce776dabdbe576bc0736d1dfc268748945edb63d63bf0517a632791e57ef68bdd9bcd6e722fdbb3cd21300cf720aec8913a7bd13b504e61d3c2072e05f64334c8332533e98bffba27e726bdc512ce8ddaf26e78d027e538ea02cd3147da30a617abcb631e57810628f69bf59303bae363d964644ee34698e1f09d1396c25934e4dcd88d992388de8f9ca94494e9320d745427dedd5ed1e900bf1628c4156246feddebf985e057a13668734966a40dd63891079b89c6dc0caff8a65fbbea1c2ce941b1</script> <div class="hbe hbe-content"> <div class="hbe hbe-input hbe-input-default"> <input class="hbe hbe-input-field hbe-input-field-default" type="password" id="hbePass"> <label class="hbe hbe-input-label hbe-input-label-default" for="hbePass"> <span class="hbe hbe-input-label-content hbe-input-label-content-default">Hey, password is required here.</span> </label> </div> </div></div><script data-pjax src="/lib/hbe.js"></script><link href="/css/hbe.style.css" rel="stylesheet" type="text/css">]]></content>
<categories>
<category> proxy </category>
</categories>
<tags>
<tag> proxy </tag>
<tag> git </tag>
<tag> ubuntu </tag>
</tags>
</entry>
<entry>
<title>汽车搭火教程</title>
<link href="//post/car-start.html"/>
<url>//post/car-start.html</url>
<content type="html"><![CDATA[<p>汽车搭火教程</p><img src="/post/car-start/start.png" class="" title="car-start.png"><span id="more"></span>]]></content>
<categories>
<category> 生活 </category>
</categories>
<tags>
<tag> 汽车 </tag>
<tag> 搭火 </tag>
</tags>
</entry>
<entry>
<title>Gradle发布MavenCenter和Nexus私服插件</title>
<link href="//post/gradle-maven.html"/>
<url>//post/gradle-maven.html</url>
<content type="html"><![CDATA[<p>基于<code>Java</code>语言与<code>Gradle Api</code>开发的<code>Gradle Plugin</code>,本<code>Gradle插件</code>可以让你的<code>library</code>发布到<code>MavenCenter</code>和自己的<code>nexus</code>私服变得非常容易。<br>内置了阿里云<code>Maven</code>中央仓库,其中配置了<code>aliyun</code>代理的<code>central</code>、<code>jcenter</code>、<code>google</code>。</p><img src="/post/gradle-maven/gradle-publish-plugin.png" class="" title="gradle-publish-plugin.png"><span id="more"></span><h3 id="一、最新版本-根目录build-gradle"><a href="#一、最新版本-根目录build-gradle" class="headerlink" title="一、最新版本(根目录build.gradle)"></a>一、最新版本(根目录build.gradle)</h3><pre class="line-numbers language-bash" data-language="bash"><code class="language-bash">classpath("io.github.szhittech:gradle-maven:0.1.0")</code></pre><h3 id="二、功能简介"><a href="#二、功能简介" class="headerlink" title="二、功能简介"></a>二、功能简介</h3><ul><li>支持发布多种类型的库, 例如:<code>Java</code>、<code>Android</code>、<code>Kotlin</code>;</li><li>支持在新的<code>gradle</code>中依赖方式 <code>api / implementation</code>;</li><li>支持签名库资源,<code>包括sources</code>、<code>Javadoc</code>、<code>POM</code>(需要<code>Gradle Version >= 4.8</code>)</li><li>本插件内置了<code>signing</code>签名信息与文件(<code>secring.gpg</code>)</li></ul><h3 id="三、使用步骤"><a href="#三、使用步骤" class="headerlink" title="三、使用步骤"></a>三、使用步骤</h3><h4 id="1-在根目录build-gradle中新增如下代码"><a href="#1-在根目录build-gradle中新增如下代码" class="headerlink" title="1. 在根目录build.gradle中新增如下代码"></a>1. 在根目录<code>build.gradle</code>中新增如下代码</h4><pre class="line-numbers language-bash" data-language="bash"><code class="language-bash">classpath("io.github.szhittech:gradle-maven:0.1.0")</code></pre><h4 id="2-在library-build-gradle中新增如下代码"><a href="#2-在library-build-gradle中新增如下代码" class="headerlink" title="2. 在library/build.gradle中新增如下代码"></a>2. 在<code>library/build.gradle</code>中新增如下代码</h4><pre class="line-numbers language-gradle" data-language="gradle"><code class="language-gradle">apply plugin: 'gradle.maven'</code></pre><h3 id="四、发布MavenCenter步骤"><a href="#四、发布MavenCenter步骤" class="headerlink" title="四、发布MavenCenter步骤"></a>四、发布<code>MavenCenter</code>步骤</h3><h4 id="1-配置根目录下gradle-properties"><a href="#1-配置根目录下gradle-properties" class="headerlink" title="1. 配置根目录下gradle.properties"></a>1. 配置根目录下<code>gradle.properties</code></h4><p>如果发布到<code>MavenCenter</code>,该文件无需配置</p><h4 id="2-配置library-build-gradle"><a href="#2-配置library-build-gradle" class="headerlink" title="2. 配置library/build.gradle"></a>2. 配置<code>library/build.gradle</code></h4><pre class="line-numbers language-gradle" data-language="gradle"><code class="language-gradle">ext { groupId = "io.github.szhittech" name = "gradle-maven" version = "0.0.0-SNAPSHOT" description = "A Gradle Plugin For Java、Android、Kotlin." url = "https://e.coding.net/clife-devops/clifepublic/gradle-maven.git" connection = "scm:[email protected]:szhittech/clifesdk.git" authorId = "uuxia" authorName = "xiamoumou" authorEmail = "[email protected]"}</code></pre><table><thead><tr><th align="left">参数</th><th align="left">必选</th><th>描述</th></tr></thead><tbody><tr><td align="left">groupId</td><td align="left"><font color="red">是</font></td><td>项目组织唯一的标识符</td></tr><tr><td align="left">name</td><td align="left"><font color="red">是</font></td><td>项目名称</td></tr><tr><td align="left">version</td><td align="left"><font color="red">是</font></td><td>项目版本。有<code>-SNAPSHOT</code>发布快照,没有发布<code>release</code>版</td></tr><tr><td align="left">description</td><td align="left">否</td><td>项目描述</td></tr><tr><td align="left">url</td><td align="left">否</td><td>项目地址</td></tr><tr><td align="left">connection</td><td align="left">否</td><td>项目地址</td></tr><tr><td align="left">authorId</td><td align="left">否</td><td>作者ID</td></tr><tr><td align="left">authorName</td><td align="left">否</td><td>作者姓名</td></tr><tr><td align="left">authorEmail</td><td align="left">否</td><td>作者邮箱</td></tr></tbody></table><h4 id="3-执行发布任务"><a href="#3-执行发布任务" class="headerlink" title="3. 执行发布任务"></a>3. 执行发布任务</h4><img src="/post/gradle-maven/maven.jpg" class="" title="发布Maven"><p>如上图,点击<code>uploadToMaven</code>,即可将库发布到MavenCenter</p><p>发布<code>MavenCenter</code>成功后 <code>Release</code>版步审核步骤如下:</p><ol><li>上述步骤成功后,请登录<a href="https://s01.oss.sonatype.org/">https://s01.oss.sonatype.org/</a>;</li><li>页面左侧栏点击<code>Build Promotion</code>-><code>Staging Repositories</code>;</li><li>在<code>Staging Repositories</code>选项卡可以看到刚提交的release版本库,如:<code>iogithubszhittect-xxxx</code>;</li><li>勾选<code>iogithubszhittect-xxxx</code>,点击<code>Close</code>;</li><li>稍等几十秒 <code>Refresh</code>,再次勾选<code>iogithubszhittect-xxxx</code>,点击<code>Release</code>,即可发布成功,等待大概4小时;</li></ol><h4 id="4-自定Maven-oss账号配置"><a href="#4-自定Maven-oss账号配置" class="headerlink" title="4. 自定Maven oss账号配置"></a>4. 自定<code>Maven oss</code>账号配置</h4><p>因本插件与<code>groupId = "io.github.szhittech"</code>绑定,如果用户需要添加自己的<code>groupid</code>,则需要在<code>gradle.properties</code>配置<code>Maven oss</code>账号</p><p><code>Maven oss</code>账号注册,请至<a href="https://s01.oss.sonatype.org/">https://s01.oss.sonatype.org/</a>注册</p><p><code>gradle.properties</code>配置如下:</p><pre class="line-numbers language-gradle" data-language="gradle"><code class="language-gradle">maven.name=mavenmaven.username=你的oss账号maven.password=你的oss密码maven.release=https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/maven.snapshot=https://s01.oss.sonatype.org/content/repositories/snapshots/</code></pre><h3 id="五、发布Nexus私服步骤"><a href="#五、发布Nexus私服步骤" class="headerlink" title="五、发布Nexus私服步骤"></a>五、发布<code>Nexus</code>私服步骤</h3><h4 id="1-配置根目录下gradle-properties-1"><a href="#1-配置根目录下gradle-properties-1" class="headerlink" title="1. 配置根目录下gradle.properties"></a>1. 配置根目录下<code>gradle.properties</code></h4><pre class="line-numbers language-bash" data-language="bash"><code class="language-bash">nexus.name=codingcoding.username=xiaoli.xia@clife.cncoding.password=xxxxxxcoding.snapshot=https://clife-devops-maven.pkg.coding.net/repository/public-repository/maven-snapshots/coding.release=https://clife-devops-maven.pkg.coding.net/repository/public-repository/maven-releases/</code></pre><table><thead><tr><th align="left">参数</th><th align="left">必选</th><th>描述</th></tr></thead><tbody><tr><td align="left">nexus.name</td><td align="left">是</td><td>自定义前缀名称,本例<code>coding</code>,下面字段就都以<code>coding</code>为前缀</td></tr><tr><td align="left">coding.username</td><td align="left">是</td><td>私服用户名</td></tr><tr><td align="left">coding.password</td><td align="left">是</td><td>私服密码</td></tr><tr><td align="left">coding.snapshot</td><td align="left">是</td><td>私服快照版上传地址</td></tr><tr><td align="left">coding.release</td><td align="left">是</td><td>私服<code>release</code>版上传地址</td></tr></tbody></table><h4 id="2-配置library-build-gradle-1"><a href="#2-配置library-build-gradle-1" class="headerlink" title="2. 配置library/build.gradle"></a>2. 配置<code>library/build.gradle</code></h4><pre class="line-numbers language-gradle" data-language="gradle"><code class="language-gradle">ext { groupId = "io.github.szhittech" name = "gradle-maven" version = "0.0.0-SNAPSHOT" description = "A Gradle Plugin For Java、Android、Kotlin." url = "https://e.coding.net/clife-devops/clifepublic/gradle-maven.git" connection = "scm:[email protected]:szhittech/clifesdk.git" authorId = "uuxia" authorName = "xiamoumou" authorEmail = "[email protected]"}</code></pre><table><thead><tr><th align="left">参数</th><th align="left">必选</th><th>描述</th></tr></thead><tbody><tr><td align="left">groupId</td><td align="left"><font color="red">是</font></td><td>项目组织唯一的标识符</td></tr><tr><td align="left">name</td><td align="left"><font color="red">是</font></td><td>项目名称</td></tr><tr><td align="left">version</td><td align="left"><font color="red">是</font></td><td>项目版本。有<code>-SNAPSHOT</code>发布快照,没有发布<code>release</code>版</td></tr><tr><td align="left">description</td><td align="left">否</td><td>项目描述</td></tr><tr><td align="left">url</td><td align="left">否</td><td>项目地址</td></tr><tr><td align="left">connection</td><td align="left">否</td><td>项目地址</td></tr><tr><td align="left">authorId</td><td align="left">否</td><td>作者ID</td></tr><tr><td align="left">authorName</td><td align="left">否</td><td>作者姓名</td></tr><tr><td align="left">authorEmail</td><td align="left">否</td><td>作者邮箱</td></tr></tbody></table><h4 id="3-执行发布任务-1"><a href="#3-执行发布任务-1" class="headerlink" title="3. 执行发布任务"></a>3. 执行发布任务</h4><img src="/post/gradle-maven/nexus.jpg" class="" title="发布Maven"><p>如上图,点击<code>uploadToCoding</code>,即可将库发布到Nexus私服</p><p><strong>注意:这里的<code>Coding</code>就是上文自定义的前缀(<code>nexus.name</code>)</strong></p><p>友情链接:</p><p><a href="https://blog.csdn.net/zyw0101/article/details/120670836?utm_medium=distribute.pc_aggpage_search_result.none-task-blog-2~aggregatepage~first_rank_ecpm_v1~rank_v31_ecpm-2-120670836.pc_agg_new_rank&utm_term=android%E5%8F%91%E5%B8%83maven&spm=1000.2123.3001.4430">1. android发布三方库到远程maven仓库详细教程</a></p><p><a href="https://mp.weixin.qq.com/s/FVR6_zMp5DxO5N4ptVuA6g">2. 发布Android Lib到Maven Central</a></p>]]></content>
<categories>
<category> gradle </category>
<category> maven </category>
</categories>
<tags>
<tag> java </tag>
<tag> gradle </tag>
<tag> android </tag>
<tag> maven </tag>
<tag> Kotlin </tag>
</tags>
</entry>
<entry>
<title>netty粘包断包处理</title>
<link href="//post/netty-tcp-packet-decoder.html"/>
<url>//post/netty-tcp-packet-decoder.html</url>
<content type="html"><![CDATA[<p>基于Netty的TCP Server,处理二进制数据断包和粘包,以及tcp发送字符串的截取处理!</p><span id="more"></span><p>基于Netty的TCP Server,处理二进制数据断包和粘包,以及tcp发送字符串的截取处理!</p><!--more--><h2 id="一、5A协议在Netty中处理断包粘包"><a href="#一、5A协议在Netty中处理断包粘包" class="headerlink" title="一、5A协议在Netty中处理断包粘包"></a>一、5A协议在Netty中处理断包粘包</h2><pre class="line-numbers language-code" data-language="code"><code class="language-code"> 长度[2] 1 1 设备编码[8] Mac地址[6] 帧序号[4] 保留[8] 命令字[2] Body CRC2[2]5A 0042 40 00 00000199000B0301 8C18D9FFEB9D 00000046 0000000000000000 0104 0000000001000301000000000000000000000003000200000000000000000000 050B说明: 1. 长度len=0042(HEX)=66=(34+32)不包含5A; 2. 空包长度total=35; 3. 包头5A(1byte)不算在len区;int maxFrameLength = 65535; (len是两个byte,所以最大长度是无符号两个byte的最大值)int lengthFieldOffset = 1; (len的索引下表是1,下表从0开始)int lengthFieldLength = 2; (len是两个byte)int lengthAdjustment = -2; (netty从len后面开始读取,5A不在len中,len又是2byte,所以这里是-2)int initialBytesToStrip = 0; (这个0表示完整的协议内容,如果不想要5A,那么这里就是1)socketChannel.pipeline().addLast(new LengthFieldBasedFrameDecoder(maxFrameLength, lengthFieldOffset, lengthFieldLength, lengthAdjustment, initialBytesToStrip));测试断包发送:完整数据包:5A0042400000000199000B03018C18D9FFEB9D00000046000000000000000001040000000001000301000000000000000000000003000200000000000000000000050B第一次发送(一包半):5A0042400000000199000B03018C18D9FFEB9D00000046000000000000000001040000000001000301000000000000000000000003000200000000000000000000050B 5A0042400000000199000B03018C18D9FFEB9D0000004600000000000000000104第二次发送(补齐后半包):0000000001000301000000000000000000000003000200000000000000000000050B</code></pre><h2 id="二、水机"><a href="#二、水机" class="headerlink" title="二、水机"></a>二、水机</h2><pre class="line-numbers language-code" data-language="code"><code class="language-code">起始码 功能码 数据长度 Body CRCA2 10 0E 0102030405060708091011121314 050B说明:1.len=0E(HEX)=14,这里的len仅仅是Body的长度,不包含head的长度;lengthFieldOffset = 2lengthFieldLength = 1lengthAdjustment = 2 initialBytesToStrip = 0maxFrameLength = 255</code></pre><p><a href="https://blog.csdn.net/lzwglory/article/details/80242209">https://blog.csdn.net/lzwglory/article/details/80242209</a></p><p><a href="https://blog.csdn.net/zougen/article/details/79037675">https://blog.csdn.net/zougen/article/details/79037675</a></p><p><a href="https://www.jianshu.com/p/a0a51fd79f62">https://www.jianshu.com/p/a0a51fd79f62</a></p><p><a href="https://www.cnblogs.com/workharder/p/12325908.html">https://www.cnblogs.com/workharder/p/12325908.html</a></p>]]></content>
<categories>
<category> netty </category>
</categories>
<tags>
<tag> netty </tag>
<tag> tcp </tag>
<tag> server </tag>
</tags>
</entry>
<entry>
<title>树莓派设置proxy</title>
<link href="//post/pi-proxy.html"/>
<url>//post/pi-proxy.html</url>
<content type="html"><![CDATA[<p>树莓派设置proxy</p><span id="more"></span><pre><code>设置步骤:1. cd /etc/apt/apt.conf.d2. sudo nano 10proxy3. Acquire::http::Proxy "http://192.168.31.53:1090";4. reboot</code></pre>]]></content>
<categories>
<category> Raspberry </category>
<category> proxy </category>
</categories>
<tags>
<tag> shadowsocks </tag>
<tag> proxy </tag>
<tag> raspberry </tag>
</tags>
</entry>
<entry>
<title>git使用SSH进行无密码身份验证</title>
<link href="//post/gitssh.html"/>
<url>//post/gitssh.html</url>
<content type="html"><![CDATA[<p>git使用SSH进行无密码身份验证</p><span id="more"></span><h2 id="一、生成key"><a href="#一、生成key" class="headerlink" title="一、生成key"></a>一、生成key</h2><h3 id="ed25519方式"><a href="#ed25519方式" class="headerlink" title="ed25519方式"></a>ed25519方式</h3><pre class="line-numbers language-none"><code class="language-none">ssh-keygen -t ed25519 -C "[email protected]"cat ~/.ssh/id_ed25519.pub</code></pre><h3 id="rsa方式"><a href="#rsa方式" class="headerlink" title="rsa方式"></a>rsa方式</h3><pre class="line-numbers language-none"><code class="language-none">ssh-keygen -t rsa -C "[email protected]"cat ~/.ssh/id_rsa.pub</code></pre><hr><h2 id="二、测试"><a href="#二、测试" class="headerlink" title="二、测试"></a>二、测试</h2><h3 id="github"><a href="#github" class="headerlink" title="github"></a>github</h3><pre class="line-numbers language-none"><code class="language-none">ssh -T [email protected]</code></pre><h3 id="gitee"><a href="#gitee" class="headerlink" title="gitee"></a>gitee</h3><pre class="line-numbers language-none"><code class="language-none">ssh -T [email protected]</code></pre><h3 id="coding"><a href="#coding" class="headerlink" title="coding"></a>coding</h3><pre class="line-numbers language-none"><code class="language-none">ssh -T [email protected]</code></pre><h2 id="注意"><a href="#注意" class="headerlink" title="注意"></a>注意</h2><hr><p>在个人设置里面添加前,必须删除单独项目中添加的ssh key!!!</p>]]></content>
<categories>
<category> Git </category>
<category> SSH </category>
</categories>
<tags>
<tag> git </tag>
<tag> github </tag>
<tag> gitee </tag>
<tag> coding </tag>
</tags>
</entry>
<entry>
<title>centos服务器程序安装指南</title>
<link href="//post/centos-server.html"/>
<url>//post/centos-server.html</url>
<content type="html"><![CDATA[<p>主要记录我的centos服务器上的服务环境安装,frp、nginx配置、java程序、mysql安装、个人博客hexo。</p><span id="more"></span><h2 id="1-nginx配置"><a href="#1-nginx配置" class="headerlink" title="1. nginx配置"></a>1. nginx配置</h2><pre class="line-numbers language-none"><code class="language-none">安装yum install nginx配置代码nano /etc/nginx/nginx.conf</code></pre><h3 id="nginx-conf"><a href="#nginx-conf" class="headerlink" title="nginx.conf"></a>nginx.conf</h3><pre class="line-numbers language-none"><code class="language-none">user root;worker_processes auto;error_log /var/log/nginx/error.log;pid /run/nginx.pid;include /usr/share/nginx/modules/*.conf;events {worker_connections 1024;}http {log_format main '$remote_addr - $remote_user [$time_local] "$request" ''$status $body_bytes_sent "$http_referer" ''"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; client_max_body_size 500m; include /etc/nginx/mime.types; default_type application/octet-stream; include /etc/nginx/conf.d/*.conf;}</code></pre><h3 id="admin-conf"><a href="#admin-conf" class="headerlink" title="admin.conf"></a>admin.conf</h3><pre class="line-numbers language-none"><code class="language-none">server { listen 80; server_name admin.uuxia.cn; location / { index index.html index.htm; proxy_set_header Host $host; proxy_pass https://127.0.0.1:8082/; proxy_set_header Upgrade $http_upgrade; proxy_http_version 1.1; proxy_set_header Connection "upgrade"; proxy_redirect https://127.0.0.1/admin https://127.0.0.1:8080/; } }</code></pre><h3 id="file-conf"><a href="#file-conf" class="headerlink" title="file.conf"></a>file.conf</h3><pre class="line-numbers language-none"><code class="language-none">autoindex on;# 显示目录autoindex_exact_size off;# 显示文件大小autoindex_localtime on;# 显示文件时间server { listen 80; server_name file.uuxia.cn; charset gbk,utf-8; location / { root /home/; index index.html index.htm; charset utf-8; } }</code></pre><h3 id="cloud-conf"><a href="#cloud-conf" class="headerlink" title="cloud.conf"></a>cloud.conf</h3><pre class="line-numbers language-none"><code class="language-none">server { listen 80 default_server; server_name cloud.uuxia.cn; location / { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_redirect off; proxy_pass http://127.0.0.1:5212; # 如果您要使用本地存储策略,请将下一行注释符删除,并更改大小为理论最大文件尺寸 # client_max_body_size 20000m; } }</code></pre><h3 id="java-conf"><a href="#java-conf" class="headerlink" title="java.conf"></a>java.conf</h3><pre class="line-numbers language-none"><code class="language-none">server { listen 80; #listen [::]:80 default_server; server_name uuxia.cn; #root /usr/share/nginx/html; #charset gbk,utf-8;# charset utf-8; location ^~ /frp_server_web/{ proxy_set_header X-Real-IP $remote_addr; proxy_set_header Host $http_host; proxy_pass http://127.0.0.1:9090; } location / { root /home/file/xxl6097.github.io; index index.html index.htm; charset utf-8; } location /file { alias /home/file; autoindex on; autoindex_exact_size off; autoindex_localtime on; charset utf-8; } location /websocket{ proxy_pass https://127.0.0.1:8082; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_read_timeout 3600s; } location /admin/ { index index.html index.htm; proxy_set_header Host $host; proxy_pass https://127.0.0.1:8082/; proxy_set_header Upgrade $http_upgrade; proxy_http_version 1.1; proxy_set_header Connection "upgrade"; proxy_redirect https://127.0.0.1/admin https://127.0.0.1:8080/; } location ~* ^(/v2|/webjars|/swagger-resources|/swagger-ui.html){ proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $remote_addr; #proxy_set_header Host $host:$server_port; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Port $server_port; proxy_pass https://127.0.0.1:8082; # 后端服务地址 } location /v1 { proxy_set_header Host $host; add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Headers' 'X-Requested-With'; add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS'; proxy_pass https://127.0.0.1:8082; } error_page 404 /404.html; location = /40x.html { } error_page 500 502 503 504 /50x.html; location = /50x.html { } }# Settings for a TLS enabled server.# server { listen 443 ssl http2 default_server; # listen [::]:443 ssl http2 default_server; server_name uuxia.cn; # root /usr/share/nginx/html; ssl_certificate "/etc/pki/nginx/server.crt"; ssl_certificate_key "/etc/pki/nginx/private/server.key"; ssl_session_cache shared:SSL:1m; ssl_session_timeout 10m; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE; #ssl_ciphers PROFILE=SYSTEM; ssl_prefer_server_ciphers on;# charset gbk,utf-8; client_max_body_size 500m; location / { root /home/file/xxl6097.github.io; index index.html index.htm; #proxy_pass https://127.0.0.1:8082/; #proxy_redirect https://127.0.0.1/admin https://127.0.0.1:8082/; charset utf-8; } location /file { alias /home/file; autoindex on; autoindex_exact_size off; autoindex_localtime on; charset utf-8; } location /v1 { proxy_set_header Host $host; add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Headers' 'X-Requested-With'; add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS'; proxy_pass https://127.0.0.1:8082; } location /admin/ { index index.html index.htm; proxy_set_header Host $host; proxy_pass https://127.0.0.1:8082/; proxy_set_header Upgrade $http_upgrade; proxy_http_version 1.1; proxy_set_header Connection "upgrade"; proxy_redirect https://127.0.0.1/admin https://127.0.0.1:8080/; } location ~* ^(/v2|/webjars|/swagger-resources|/swagger-ui.html){ proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $remote_addr; #proxy_set_header Host $host:$server_port; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Port $server_port; proxy_pass https://127.0.0.1:8082; # 后端服务地址 } location /websocket{ proxy_pass https://127.0.0.1:8082; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_read_timeout 3600s; } error_page 404 /404.html; location = /40x.html { }# error_page 500 502 503 504 /50x.html; location = /50x.html { } }</code></pre><hr><h2 id="2-mysql安装配置"><a href="#2-mysql安装配置" class="headerlink" title="2. mysql安装配置"></a>2. mysql安装配置</h2><pre class="line-numbers language-none"><code class="language-none">1.下载MySQLRed Hat Enterprise Linux / Oracle Linux2. 选择 `Red Hat Enterprise Linux 8 / Oracle Linux 8 (x86, 64-bit), RPM Bundle</code></pre><pre class="line-numbers language-none"><code class="language-none">安装wget https://cdn.mysql.com//Downloads/MySQL-8.0/mysql-8.0.28-1.el8.x86_64.rpm-bundle.tartar -xvf mysql-8.0.28-1.el8.x86_64.rpm-bundle.tar rpm -ivh mysql-community-common-8.0.28-1.el8.x86_64.rpm --nodeps --forcerpm -ivh mysql-community-libs-8.0.28-1.el8.x86_64.rpm --nodeps --forcerpm -ivh mysql-community-client-8.0.28-1.el8.x86_64.rpm --nodeps --forcerpm -ivh mysql-community-server-8.0.28-1.el8.x86_64.rpm --nodeps --force通过 rpm -qa | grep mysql 命令查看 mysql 的安装包</code></pre><pre class="line-numbers language-none"><code class="language-none">通过以下命令,完成对 mysql 数据库的初始化和相关配置mysqld --initialize;chown mysql:mysql /var/lib/mysql -R;systemctl start mysqld.service;systemctl enable mysqld;</code></pre><p>通过 <code>cat /var/log/mysqld.log | grep password</code> 命令查看数据库的密码</p><p>通过 <code>mysql -uroot -p</code> 敲回车键进入数据库登陆界面</p><p>通过 <code>ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'Xxl2475431305.';</code> 命令来修改密码<br><code>ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'Xxl2475431305.';</code><br>这下密码改成了 root</p><p>通过 exit; 命令退出 MySQL,然后通过新密码再次登陆</p><p>通过以下命令,进行远程访问的授权</p><pre class="line-numbers language-none"><code class="language-none">create user 'root'@'%' identified with mysql_native_password by 'root';grant all privileges on *.* to 'root'@'%' with grant option;flush privileges;</code></pre><p>sqlyog链接时出现2058异常</p><p><code>ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password';</code><br>其中password为自己修改的密码。然后SQLyog中重新连接,则可连接成功,OK。</p><p>如果报错:ERROR 1396 (HY000): Operation ALTER USER failed for ‘root’@’localhost’则使用下面命令:</p><p><code>ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'Xxl2475431305.';</code></p><hr><h2 id="3-JDK安装配置"><a href="#3-JDK安装配置" class="headerlink" title="3. JDK安装配置"></a>3. JDK安装配置</h2><h3 id="方式一(推荐)"><a href="#方式一(推荐)" class="headerlink" title="方式一(推荐)"></a>方式一(推荐)</h3><pre class="line-numbers language-none"><code class="language-none">查询安装的jdk版本yum -y list java*安装jdk1.8yum install -y java-11-openjdk.x86_64</code></pre><h3 id="方式二"><a href="#方式二" class="headerlink" title="方式二"></a>方式二</h3><h4 id="下载"><a href="#下载" class="headerlink" title="下载"></a>下载</h4><pre class="line-numbers language-none"><code class="language-none">https://www.oracle.com/java/technologies/downloads/#java8Mac:https://download.oracle.com/otn/java/jdk/8u321-b07/df5ad55fdd604472a86a45a217032c7d/jdk-8u321-macosx-x64.dmgLinux:https://download.oracle.com/otn/java/jdk/8u321-b07/df5ad55fdd604472a86a45a217032c7d/jdk-8u321-linux-x64.tar.gzWindows:https://download.oracle.com/otn/java/jdk/8u321-b07/df5ad55fdd604472a86a45a217032c7d/jdk-8u321-windows-x64.exe选择 `jdk-8u321-linux-x64.tar.gz`解压 `tar -zxvf jdk-8u321-linux-x64.tar.gz`</code></pre><pre class="line-numbers language-none"><code class="language-none">修改环境变量 `nano /etc/profile`export JAVA_HOME=/usr/lib/jdk1.8.0_321export CLASSPATH=.:$JAVA_HOME/jre/lib/rt.jar:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jarexport PATH=$PATH:$JAVA_HOME/binsource /etc/profile</code></pre><hr><h2 id="4-gralde安装"><a href="#4-gralde安装" class="headerlink" title="4. gralde安装"></a>4. gralde安装</h2><pre class="line-numbers language-none"><code class="language-none">wget https://services.gradle.org/distributions/gradle-6.7-bin.zipunzip gradle-6.7-bin.zipnano ~/.bash_profilePATH=$PATH:/usr/lib/gradle-6.7/binsource ~/.bash_profile</code></pre><hr><h2 id="5-安装frps安装"><a href="#5-安装frps安装" class="headerlink" title="5. 安装frps安装"></a>5. 安装frps安装</h2><p>服务端配置</p><pre class="line-numbers language-none"><code class="language-none">[common]bind_port = 8000token = xxxxxxxxxdashboard_port=8888dashboard_user = admindashboard_pwd = adminvhost_http_port = 9090vhost_https_port = 9091subdomain_host = uuxia.cn</code></pre><h2 id="客户端配置"><a href="#客户端配置" class="headerlink" title="客户端配置"></a>客户端配置<br><pre class="line-numbers language-none"><code class="language-none">[common]tls_enable = trueadmin_addr = 0.0.0.0admin_port = 7400admin_user = adminadmin_pwd = admintoken = xxxxxx#server_addr = 127.0.0.1server_addr = uuxia.cnserver_port = 8000[公司-树莓派3B]type = tcplocal_ip = 0.0.0.0local_port = 22remote_port = 2222[公司-FRP客户端管理页面]type = tcplocal_ip = 0.0.0.0local_port = 7400remote_port = 7401[公司-win]type = tcplocal_ip = 192.168.31.53local_port = 3389remote_port = 7001[公司-iMac-VNC]type = tcplocal_ip = 192.168.31.92local_port = 5900remote_port = 7002[公司-iMac-SSH]type = tcplocal_ip = 192.168.31.92local_port = 22remote_port = 7003</code></pre></h2><h2 id="6-安装Node-js"><a href="#6-安装Node-js" class="headerlink" title="6. 安装Node.js"></a>6. 安装Node.js</h2><hr><pre class="line-numbers language-none"><code class="language-none">1 下载官网地址:https://nodejs.org/en/download/wget https://nodejs.org/dist/v10.24.0/node-v10.24.0-linux-x64.tar.gz</code></pre><pre class="line-numbers language-none"><code class="language-none">安装tar -xvf node-v10.24.0-linux-x64.tar.gzmv node-v10.24.0-linux-x64 /opt/NodejsNODE_HOME=/opt/Nodejsexport PATH=$NODE_HOME/bin:$PATHsource /etc/profilenpm install -g hexo-clinpm uninstall hexo-cli -g 推荐这个,成功卸载</code></pre><hr><h2 id="7-页脚备案代码"><a href="#7-页脚备案代码" class="headerlink" title="7. 页脚备案代码"></a>7. 页脚备案代码</h2><pre class="line-numbers language-none"><code class="language-none"><div style="color:#666;text-align:center;margin-top:-10px;padding-bottom:35px;"> <p><a style="color:#666;" text-decoration:underline;" href="http://beian.miit.gov.cn/">工业和信息化部备案管理系统网站 粤ICP备2022014941号</a></p> <p>主办单位:<a style="color:#666;" text-decoration:underline;" target="_blank" href="http://uuxia.cn">悠悠科技</a></p> <p>Operated by Guangzhou ChoMeng Computer System Co., Ltd.</p></div></code></pre>]]></content>
<categories>
<category> hexo </category>
<category> nginx </category>
<category> frp </category>
</categories>
<tags>
<tag> centos </tag>
<tag> hexo </tag>
<tag> java </tag>
<tag> frp </tag>
<tag> nginx </tag>
<tag> mysql </tag>
<tag> gradle </tag>
</tags>
</entry>
<entry>
<title>hexo写文章使用说明</title>
<link href="//post/shi-yong-shuo-ming.html"/>
<url>//post/shi-yong-shuo-ming.html</url>
<content type="html"><![CDATA[<p>如何使用hexo作文章</p><span id="more"></span><h2 id="1-内容说明"><a href="#1-内容说明" class="headerlink" title="1. 内容说明"></a>1. 内容说明</h2><pre class="line-numbers language-none"><code class="language-none">---title: hexo写文章使用说明date: 2022-02-09 14:08:49tags: [写作,hexo]categories: hexo---如何使用hexo作文章<!--more--></code></pre><h2 id="2-新建文章可用Hexo命令创建:"><a href="#2-新建文章可用Hexo命令创建:" class="headerlink" title="2. 新建文章可用Hexo命令创建:"></a>2. 新建文章可用Hexo命令创建:</h2><pre class="line-numbers language-none"><code class="language-none">hexo new vpn使用</code></pre><h2 id="3-构建和发布"><a href="#3-构建和发布" class="headerlink" title="3. 构建和发布"></a>3. 构建和发布</h2><pre class="line-numbers language-none"><code class="language-none">hexo g -d</code></pre>]]></content>
<categories>
<category> Hexo </category>
</categories>
<tags>
<tag> hexo </tag>
<tag> 写作 </tag>
</tags>
</entry>
<entry>
<title>腾讯云【centos7/8】一键安装 shadowsocks-libev</title>
<link href="//post/tencent-shadowsocks.html"/>
<url>//post/tencent-shadowsocks.html</url>
<content type="html"><![CDATA[<p>CentOS 7/8 一键安装 shadowsocks-libev, 本教程仅提供学习,请勿用于商业用途和不法行为。</p><p>由于 Google BBR 需要内核版本 4.9 以上,如果安装时内核版本低于 4.9 建议先升级内核版本。</p><p>提示:CentOS 7 自带内核版本为 3.10,CentOS 8 自带内核版本为 4.18。</p><p>查看内核版本命令:</p><pre class="line-numbers language-bash" data-language="bash"><code class="language-bash">uname -r</code></pre><h3 id="1、下载脚本"><a href="#1、下载脚本" class="headerlink" title="1、下载脚本"></a>1、下载脚本</h3><p>一键脚本已集成TCP优化、自动开启Google BBR(限 4.9 或更高版本内核)、自动安装 shadowsocks-libev</p><pre class="line-numbers language-bash" data-language="bash"><code class="language-bash">wget https://down.24kplus.com/linux/shadowsocks/centos-shadowsocks-libev.sh</code></pre><h3 id="2、执行脚本进行安装"><a href="#2、执行脚本进行安装" class="headerlink" title="2、执行脚本进行安装"></a>2、执行脚本进行安装</h3><pre class="line-numbers language-bash" data-language="bash"><code class="language-bash">chmod +x centos-shadowsocks-libev.sh && ./centos-shadowsocks-libev.sh</code></pre><h3 id="3、根据shell脚本提示输入相关信息"><a href="#3、根据shell脚本提示输入相关信息" class="headerlink" title="3、根据shell脚本提示输入相关信息"></a>3、根据shell脚本提示输入相关信息</h3><p>1、提示设置SS密码,输入自定义密码后按回车,也可以直接按回车使用默认密码<br>2、接下来选择SS要使用的服务器端口,输入自己喜欢的端口, 也可以直接按回车使用默认端口<br>3、 然后选择加密方式(仅保留相对安全的加密方式),如果选择chacha20的话,就输入对应序号3,按回车继续<br>4、 安装完成后,会有如下图安装成功的提示,记住各项信息,在客户端连接时需要用到</p><h3 id="4、shadowsocks管理"><a href="#4、shadowsocks管理" class="headerlink" title="4、shadowsocks管理"></a>4、shadowsocks管理</h3><pre class="line-numbers language-bash" data-language="bash"><code class="language-bash">#!/bin/bashfunction status() { systemctl status shadowsocks-libev.service}function restart() { systemctl restart shadowsocks-libev.service}function log() { journalctl -f -u shadowsocks-libev.service}function m() { echo "1. 重启" echo "2. 重看状态" echo "3. 查看日志" echo "请输入编号:" read index case "$index" in [1]) (restart);; [2]) (status);; [3]) (log);; *) echo "exit" ;; esac}m</code></pre>]]></content>
<categories>
<category> VPN </category>
<category> shadowsocks </category>
<category> centos7 </category>
</categories>
<tags>
<tag> shadowsocks </tag>
<tag> centos </tag>
<tag> 腾讯云 </tag>
</tags>
</entry>
<entry>
<title>国庆长假新疆旅行-北疆环游</title>
<link href="//post/xj-north-circle.html"/>
<url>//post/xj-north-circle.html</url>
<content type="html"><![CDATA[<h1 id="行程速览"><a href="#行程速览" class="headerlink" title="行程速览"></a>行程速览</h1><img src="/post/xj-north-circle/xj-todo-list.png" class=""><h1 id="注意事项:"><a href="#注意事项:" class="headerlink" title="注意事项:"></a>注意事项:</h1><ol><li>日照强烈日夜温差大,做好防晒带好冲锋衣或羽绒服(特别是喀纳斯地区,观鱼亭山顶大风变幻莫测);</li><li>新疆各景点之间距离较远,基本每天换酒店,一次性生活用品带足(建议内裤袜子毛巾也最好买一次性);</li><li>自驾比较随性,建议当天订隔天酒店即可(最好订景区附近城镇,性价比高又干净;</li><li><font color="red">车子油箱少于一半见到加油站就满上;</font></li><li>开车要注意区间限速,哪怕前面一望无际,也只能慢慢的开;</li><li>新疆买东西是按公斤计算,吃饭菜量很大,北方人可能没感觉,南方去的点菜要注意量;</li><li>治安绝对可靠安全,各种检查,当地百姓纯朴善良(详细后文会说);</li><li>外地卡去新疆只有克拉玛依有4G,其他地区一概没有,建议到新疆第一天办张当地上网卡.</li></ol><h4 id="D1-9月27号-深圳-乌鲁木齐"><a href="#D1-9月27号-深圳-乌鲁木齐" class="headerlink" title="D1(9月27号):深圳-乌鲁木齐"></a>D1(9月27号):深圳-乌鲁木齐</h4><h5 id="行程安排:"><a href="#行程安排:" class="headerlink" title="行程安排:"></a>行程安排:</h5><ol><li>去酒店放下行李;</li><li>时间充足的话,可以去【新疆博物馆】,感怀西域历史的沧桑变化;</li><li>如果想要体验感受浓郁异域风情,推荐可以去【二道桥国际大巴扎】,独特的西域文化,琳琅满目的商品及各种新疆特色美食,说不定还能淘到不少好货;</li><li>找超市备货;</li><li>预定好下一站可可托海的住宿;</li></ol><img src="/post/xj-north-circle/xj-jipiao.jpeg" class=""><h5 id="注意事项:-1"><a href="#注意事项:-1" class="headerlink" title="注意事项:"></a>注意事项:</h5><ol><li>晚上21:00以后才会天黑;</li></ol><h4 id="D2-9月28号-乌鲁木齐-准噶尔盆地-可可苏里湖-可可托海镇"><a href="#D2-9月28号-乌鲁木齐-准噶尔盆地-可可苏里湖-可可托海镇" class="headerlink" title="D2(9月28号):乌鲁木齐-准噶尔盆地-可可苏里湖-可可托海镇"></a>D2(9月28号):乌鲁木齐-准噶尔盆地-可可苏里湖-可可托海镇</h4><h5 id="行程安排:-1"><a href="#行程安排:-1" class="headerlink" title="行程安排:"></a>行程安排:</h5><ol><li>途中小镇午餐;</li><li>继续北上穿越准噶尔盆地,驶向阿勒泰山腹地;</li><li>路经古尔班0烤馕、凉皮、炒面、烤串,地道的羊羔肉;</li><li>一路上大概过了十几个安检站</li></ol><h5 id="车程:"><a href="#车程:" class="headerlink" title="车程:"></a>车程:</h5><ol><li>约520KM(高速、国道为主);</li><li>区间测速80km;</li><li><a href="https://www.amap.com/dir?from%5Bid%5D=B03DF0668Z-to&from%5Bname%5D=%E4%B9%8C%E9%B2%81%E6%9C%A8%E9%BD%90%E5%9C%B0%E7%AA%9D%E5%A0%A1%E5%9B%BD%E9%99%85%E6%9C%BA%E5%9C%BA&from%5Blnglat%5D=87.479742,43.905808&from%5Bmodxy%5D=87.478441,43.902829&from%5Bpoitype%5D=150104&from%5Badcode%5D=650104&to%5Badcode%5D=654322&to%5Bname%5D=%E5%8F%AF%E5%8F%AF%E6%89%98%E6%B5%B7%E9%95%87&to%5Bid%5D=B038A0LO1U&to%5Bpoitype%5D=190106&to%5Blnglat%5D=89.81118900000001,47.221611&to%5Bmodxy%5D=&type=car&policy=1" title="行车路线">行车路线</a></li></ol><img src="/post/xj-north-circle/xj-img1.png" class=""><hr><h4 id="D3-9月29号-可可托海镇-可可托海国家地质公园-五彩滩-布尔津"><a href="#D3-9月29号-可可托海镇-可可托海国家地质公园-五彩滩-布尔津" class="headerlink" title="D3(9月29号):可可托海镇-可可托海国家地质公园-五彩滩-布尔津"></a>D3(9月29号):可可托海镇-可可托海国家地质公园-五彩滩-布尔津</h4><h5 id="费用:"><a href="#费用:" class="headerlink" title="费用:"></a>费用:</h5><ol><li>可可托海风景区(门票:90,区间车:36);</li><li>五彩滩景区(门票:50,建议游玩2小时);</li></ol><h5 id="行程安排:-2"><a href="#行程安排:-2" class="headerlink" title="行程安排:"></a>行程安排:</h5><ol><li>早餐后,前往“世界地质公园”【可可托海国家地质公园】,又称额尔齐斯河大峡谷;</li><li>进景区需要办理“边境通行证”,在购票处出示身份证办理即可;</li><li>景区车一路沿额尔齐斯河河谷前行;</li><li>沿途欣赏金秋的白桦林、石门、夫妻树等,游玩拍摄可可托海著名的标志【神钟山】;</li><li>之后可以沿着额尔齐斯河峡谷往里徒步深入一段;</li><li>驾车到富蕴县继续大众点评找午餐,午餐后富蕴县——北屯——布尔津——五彩滩;</li><li>游览五彩滩景区后返回布尔津,晚餐并游览著名的布尔津美食街;</li><li>9点回布尔津市区,入住布尔津国际酒店</li></ol><h5 id="注意事项:-2"><a href="#注意事项:-2" class="headerlink" title="注意事项:"></a>注意事项:</h5><ol><li><font color="red">进景区需要办理“边境通行证”,在购票处出示身份证办理即可</font></li><li>景区不必走到山顶中蒙边境,后半程风景和前半程类似,另外可以沿中间河边的石子路走,景色更美;</li></ol><h5 id="车程:-1"><a href="#车程:-1" class="headerlink" title="车程:"></a>车程:</h5><ol><li>自驾全程350公里,6小时左右。</li><li>布尔津-五彩滩:距离40KM,车程50分钟(此段有区间测速,60);</li><li><font color="red">富蕴县-布尔津 全程国道,有测速,而且还有流动测速(路边放个临时测速器,CT就停在暗处)</font>;</li><li><a href="https://www.amap.com/dir?from%5Badcode%5D=654322&from%5Bname%5D=%E5%8F%AF%E5%8F%AF%E6%89%98%E6%B5%B7%E9%95%87&from%5Bid%5D=B038A0LO1U-from&from%5Bpoitype%5D=190106&from%5Blnglat%5D=89.81118900000001,47.221611&from%5Bmodxy%5D=&to%5Bid%5D=B038A0LR4U&to%5Bname%5D=%E5%B8%83%E5%B0%94%E6%B4%A5%E5%8E%BF&to%5Blnglat%5D=86.874897,47.701850&to%5Bmodxy%5D=86.874897,47.701850&to%5Bpoitype%5D=190105&to%5Badcode%5D=654321&type=car&policy=1" title="行车路线">行车路线</a></li></ol><img src="/post/xj-north-circle/xj-img2.png" class=""><img src="/post/xj-north-circle/xj-img3.png" class=""><hr><h4 id="D4-9月30号-布尔津-喀纳斯-贾登峪"><a href="#D4-9月30号-布尔津-喀纳斯-贾登峪" class="headerlink" title="D4(9月30号):布尔津-喀纳斯-贾登峪"></a>D4(9月30号):布尔津-喀纳斯-贾登峪</h4><p>#####费用:</p><ol><li>门票185元/人,门票站到游客中心100元/人,游客中心到观景台120元/人,游船120元/人</li></ol><h5 id="行程安排:-3"><a href="#行程安排:-3" class="headerlink" title="行程安排:"></a>行程安排:</h5><ol><li>布尔津到贾登峪门票站,135公里,区间测速必须要开3个小时;</li><li>买喀纳斯景区门票坐景区大巴1小时到游客中心;</li><li>在游客中心用餐,然后分头行动,上观鱼台的上观鱼台(要爬1068步梯坎才能到观鱼台,去湖边的去湖边</li><li>耍了2个多小时后回游客中心坐大巴出景区;</li><li>返程沿途游览三湾(三湾里就月亮湾最为有代表性,另外两个需要清晨漫步才有感觉,这样就必须在喀纳斯景区里住);</li><li>回贾登峪后自驾1个小时前往禾木门票站,转大巴1小时到禾木村入住;</li></ol><h5 id="注意事项:-3"><a href="#注意事项:-3" class="headerlink" title="注意事项:"></a>注意事项:</h5><ol><li><font color="red">去喀纳斯之前请在布尔津把油箱加满,这来回路上没有加油站</font></li><li>进去喀纳斯一定要裹严实了,冲锋衣羽绒服都穿起来;</li><li>区间车要坐在面向车头的右手边,区间车要坐半个小时,右手边会看到山谷,左手边就只能看堡坎了..</li><li>布尔津到喀纳斯后半截的路上,大客车巨多,越往后面山路也最多,安检站也多</li></ol><h5 id="车程:-2"><a href="#车程:-2" class="headerlink" title="车程:"></a>车程:</h5><ol><li>自驾全程135公里,3小时左右。</li><li>全程区县测速限速:60km;</li><li>去程走大路,返程走小路;</li><li><a href="https://www.amap.com/dir?from%5Bid%5D=B038A0LR4U-from&from%5Bname%5D=%E5%B8%83%E5%B0%94%E6%B4%A5%E5%8E%BF&from%5Blnglat%5D=86.874897,47.701850&from%5Bmodxy%5D=86.874897,47.701850&from%5Bpoitype%5D=190105&from%5Badcode%5D=654321&to%5Bid%5D=B0FFL2UMIZ&to%5Bname%5D=%E8%B4%BE%E7%99%BB%E5%B3%AA%E9%97%A8%E7%A5%A8%E7%AB%99&to%5Blnglat%5D=87.130721,48.507338&to%5Bmodxy%5D=87.130721,48.507338&to%5Bpoitype%5D=070000&to%5Badcode%5D=654321&type=car&policy=1" title="行车路线">行车路线</a></li></ol><img src="/post/xj-north-circle/xj-img4.png" class=""><img src="/post/xj-north-circle/xj-img5.png" class=""><hr><h4 id="D5-10月1号-贾登峪-禾木一日游-禾木村"><a href="#D5-10月1号-贾登峪-禾木一日游-禾木村" class="headerlink" title="D5(10月1号):贾登峪-禾木一日游-禾木村"></a>D5(10月1号):贾登峪-禾木一日游-禾木村</h4><p>到达禾木村差不多上午10点左右。</p><h5 id="费用:-1"><a href="#费用:-1" class="headerlink" title="费用:"></a>费用:</h5><h5 id="行程安排:-4"><a href="#行程安排:-4" class="headerlink" title="行程安排:"></a>行程安排:</h5><ol><li>上午游览村庄北面的白桦林、草原;</li><li>中午回去睡了个午觉;</li><li>下午骑马到村庄南面观景台,河边游玩(强烈推荐3小时的美丽峰骑马游,200元/人,其实性价比非常之高,谁骑谁知道);</li><li>傍晚大家可以前往【禾木日落观景台】,俯瞰禾木村全景</li><li>晚上,可以干点想干的事。。。</li></ol><h5 id="注意事项:-4"><a href="#注意事项:-4" class="headerlink" title="注意事项:"></a>注意事项:</h5><ol><li>下午4、5点钟的时候太阳巨大巨晒,注意选择时间</li></ol><h5 id="车程:-3"><a href="#车程:-3" class="headerlink" title="车程:"></a>车程:</h5><ol><li>距离70KM,2个半小时车程;</li><li><a href="https://www.amap.com/dir?from%5Bid%5D=B0FFL2UMIZ-from&from%5Bname%5D=%E8%B4%BE%E7%99%BB%E5%B3%AA%E9%97%A8%E7%A5%A8%E7%AB%99&from%5Blnglat%5D=87.130721,48.507338&from%5Bmodxy%5D=87.130721,48.507338&from%5Bpoitype%5D=070000&from%5Badcode%5D=654321&to%5Bid%5D=B0FFIPUO59&to%5Bname%5D=%E7%A6%BE%E6%9C%A8%E6%9D%91&to%5Blnglat%5D=87.432910,48.568561&to%5Bmodxy%5D=87.432910,48.568561&to%5Bpoitype%5D=190108&to%5Badcode%5D=654321&type=car&policy=1" title="行车路线">行车路线</a></li></ol><img src="/post/xj-north-circle/xj-img6.png" class=""><img src="/post/xj-north-circle/xj-img7.png" class=""><hr><h4 id="D6-10月2号-禾木村-乌尔禾胡杨林-魔鬼城-乌尔禾"><a href="#D6-10月2号-禾木村-乌尔禾胡杨林-魔鬼城-乌尔禾" class="headerlink" title="D6(10月2号):禾木村-乌尔禾胡杨林-魔鬼城-乌尔禾"></a>D6(10月2号):禾木村-乌尔禾胡杨林-魔鬼城-乌尔禾</h4><h5 id="费用:-2"><a href="#费用:-2" class="headerlink" title="费用:"></a>费用:</h5><ol><li>门票+观光车 98/人</li></ol><h5 id="行程安排:-5"><a href="#行程安排:-5" class="headerlink" title="行程安排:"></a>行程安排:</h5><ol><li>6点半起床上观景台拍日出,是否能看到晨雾美景就需要点运气了;</li><li>驾车回布尔津午餐;</li><li>魔鬼城景区里坐小火车一路前行</li></ol><h5 id="注意事项:-5"><a href="#注意事项:-5" class="headerlink" title="注意事项:"></a>注意事项:</h5><ol><li>禾木景区出来的这段景色超美,路边设有多个观景台,可供停车拍照;</li><li>魔鬼城合适摄影,特别是日出和日落的时候,景区是24小时开放,但日落要10点过,不要去太早 注意选择时间</li><li><font color="red">乌尔禾,入住博玉大酒店,性价比相当高哦,附近美食也超多;</font></li><li><a href="https://go.cqmmgo.com/forum-2466-thread-47141499934173209-7-1.html" title="在马路对面吃到最好吃的一家大盘鸡!还有塔城的特色风干牛肉、特色拉条子">在马路对面吃到最好吃的一家大盘鸡!还有塔城的特色风干牛肉、特色拉条子</a>;</li></ol><h5 id="车程:-4"><a href="#车程:-4" class="headerlink" title="车程:"></a>车程:</h5><ol><li>禾木-布尔津-克拉玛依:距离470KM,10小时车程(前半段国道有区间测速,后半段高速);</li><li>布尔津-克拉玛依这段横风很大,开车要双手握紧方向盘;</li><li><a href="https://www.amap.com/dir?from%5Bid%5D=B0FFIPUO59-from&from%5Bname%5D=%E7%A6%BE%E6%9C%A8%E6%9D%91&from%5Blnglat%5D=87.432910,48.568561&from%5Bmodxy%5D=87.432910,48.568561&from%5Bpoitype%5D=190108&from%5Badcode%5D=654321&to%5Bid%5D=B03DE0004L&to%5Bname%5D=%E4%B8%96%E7%95%8C%E9%AD%94%E9%AC%BC%E5%9F%8E&to%5Blnglat%5D=85.746798,46.129675&to%5Bmodxy%5D=85.735517,46.137257&to%5Bpoitype%5D=110202&to%5Badcode%5D=650205&type=car&policy=1" title="行车路线">行车路线</a></li></ol><img src="/post/xj-north-circle/xj-img8.png" class=""><hr><h4 id="D7-10月3号-乌尔禾-果子沟大桥-赛里木湖"><a href="#D7-10月3号-乌尔禾-果子沟大桥-赛里木湖" class="headerlink" title="D7(10月3号):乌尔禾-果子沟大桥-赛里木湖"></a>D7(10月3号):乌尔禾-果子沟大桥-赛里木湖</h4><h5 id="费用:-3"><a href="#费用:-3" class="headerlink" title="费用:"></a>费用:</h5><ol><li>门票70一人</li></ol><h5 id="行程安排:-6"><a href="#行程安排:-6" class="headerlink" title="行程安排:"></a>行程安排:</h5><ol><li>中午下道去乌苏市区找大众点评美食(要稍早到达赛里木,后面景点较多,不建议在乌苏就餐);</li><li>大约下午5点才到赛里木湖,环湖一圈玩了3个小时后;</li><li>入住果子沟大桥绝佳观景台唯一的山庄;</li><li>早点的话,可以上观景台看全景。</li></ol><img src="/post/xj-north-circle/xj-img9.png" class=""><h5 id="注意事项:-6"><a href="#注意事项:-6" class="headerlink" title="注意事项:"></a>注意事项:</h5><ol><li><a href="https://go.cqmmgo.com/forum-2466-thread-47141499934173209-8-1.html" title="可入住龙岭山庄,山顶北可观赛里木湖全景,南可俯揽果子沟大桥全景">可入住龙岭山庄,山顶北可观赛里木湖全景,南可俯揽果子沟大桥全景</a>;</li><li><font color="red">龙岭山庄</font>8点半开始供应早餐</li></ol><h5 id="车程:-5"><a href="#车程:-5" class="headerlink" title="车程:"></a>车程:</h5><ol><li>自驾全程600公里,不耽误只要6个小时;</li><li><a href="https://www.amap.com/dir?from%5Bid%5D=B03DE0004L-from&from%5Bname%5D=%E4%B8%96%E7%95%8C%E9%AD%94%E9%AC%BC%E5%9F%8E&from%5Blnglat%5D=85.746798,46.129675&from%5Bmodxy%5D=85.735517,46.137257&from%5Bpoitype%5D=110202&from%5Badcode%5D=650205&to%5Bid%5D=B038D0LN33&to%5Bname%5D=%E8%B5%9B%E9%87%8C%E6%9C%A8%E6%B9%96%E6%B8%B8%E5%AE%A2%E4%B8%AD%E5%BF%83&to%5Blnglat%5D=81.394494,44.601962&to%5Bmodxy%5D=81.394578,44.601789&to%5Bpoitype%5D=070000&to%5Badcode%5D=652701&type=car&policy=1" title="行车路线">行车路线</a></li></ol><img src="/post/xj-north-circle/xj-img10.png" class=""><hr><h4 id="D8-10月4号-赛里木湖-九曲十八弯日落-巴音布鲁克镇"><a href="#D8-10月4号-赛里木湖-九曲十八弯日落-巴音布鲁克镇" class="headerlink" title="D8(10月4号):赛里木湖-九曲十八弯日落-巴音布鲁克镇"></a>D8(10月4号):赛里木湖-九曲十八弯日落-巴音布鲁克镇</h4><h5 id="费用:-4"><a href="#费用:-4" class="headerlink" title="费用:"></a>费用:</h5><h5 id="行程安排:-7"><a href="#行程安排:-7" class="headerlink" title="行程安排:"></a>行程安排:</h5><ol><li>早起去拍赛里木湖日出全景;</li><li>出发,路径伊犁看薰衣草;</li><li>午餐可以在高速服务区用餐;</li><li>看巴音布鲁克景区欣赏九曲十八弯的日落</li></ol><h5 id="注意事项:-7"><a href="#注意事项:-7" class="headerlink" title="注意事项:"></a>注意事项:</h5><ol><li>巴音布鲁克景区过了晚上8点不准进;</li><li>到达巴音布鲁克镇上,可以<font color="red">入住龙兴国际大酒店</font></li><li><font color="red">如果到的比较早,那么就今天游玩完巴音布鲁克景点</font></li></ol><h5 id="车程:-6"><a href="#车程:-6" class="headerlink" title="车程:"></a>车程:</h5><ol><li>自驾全程450公里,7小时左右。</li><li><a href="https://www.amap.com/dir?from%5Bid%5D=B038D0LN33-from&from%5Bname%5D=%E8%B5%9B%E9%87%8C%E6%9C%A8%E6%B9%96%E6%B8%B8%E5%AE%A2%E4%B8%AD%E5%BF%83&from%5Blnglat%5D=81.394494,44.601962&from%5Bmodxy%5D=81.394578,44.601789&from%5Bpoitype%5D=070000&from%5Badcode%5D=652701&to%5Badcode%5D=652827&to%5Bname%5D=%E5%B7%B4%E9%9F%B3%E5%B8%83%E9%B2%81%E5%85%8B%E9%95%87&to%5Bid%5D=B0FFIITRO1&to%5Bpoitype%5D=190106&to%5Blnglat%5D=84.15197999999998,43.033831&to%5Bmodxy%5D=&type=car&policy=1" title="行车路线">行车路线</a></li></ol><img src="/post/xj-north-circle/xj-img11.png" class=""><hr><h4 id="D9-10月5号-巴音布鲁克镇-天鹅湖-九曲十八弯-独库公路-乌鲁木齐"><a href="#D9-10月5号-巴音布鲁克镇-天鹅湖-九曲十八弯-独库公路-乌鲁木齐" class="headerlink" title="D9(10月5号):巴音布鲁克镇-天鹅湖-九曲十八弯-独库公路-乌鲁木齐"></a>D9(10月5号):巴音布鲁克镇-天鹅湖-九曲十八弯-独库公路-乌鲁木齐</h4><h5 id="费用:-5"><a href="#费用:-5" class="headerlink" title="费用:"></a>费用:</h5><ol><li>景区门票+保险+观光车,170一人</li></ol><h5 id="行程安排:-8"><a href="#行程安排:-8" class="headerlink" title="行程安排:"></a>行程安排:</h5><p>1.上午进巴音布鲁克景区游览天鹅湖和九曲十八弯;<br>2.中午在巴音布鲁克镇上撸了本次行程最美味的羊肉串后出发;<br>3.下午:号称中国最美公路的天山天路——独库公路,欣赏沿途一日四季美景;<br>4.直接杀到乌鲁木齐。</p><h5 id="注意事项:-8"><a href="#注意事项:-8" class="headerlink" title="注意事项:"></a>注意事项:</h5><ol><li>晚上8点加油站关门</li><li><font color="red">尽量早点出发,因为去乌鲁木齐有500km,最晚不能超过13点</font></li></ol><h5 id="车程:-7"><a href="#车程:-7" class="headerlink" title="车程:"></a>车程:</h5><ol><li><a href="https://www.amap.com/dir?from%5Badcode%5D=652827&from%5Bname%5D=%E5%B7%B4%E9%9F%B3%E5%B8%83%E9%B2%81%E5%85%8B%E9%95%87&from%5Bid%5D=B0FFIITRO1-from&from%5Bpoitype%5D=190106&from%5Blnglat%5D=84.15197999999998,43.033831&from%5Bmodxy%5D=&to%5Bid%5D=B03DF0668Z&to%5Bname%5D=%E4%B9%8C%E9%B2%81%E6%9C%A8%E9%BD%90%E5%9C%B0%E7%AA%9D%E5%A0%A1%E5%9B%BD%E9%99%85%E6%9C%BA%E5%9C%BA&to%5Blnglat%5D=87.479742,43.905808&to%5Bmodxy%5D=87.478441,43.902829&to%5Bpoitype%5D=150104&to%5Badcode%5D=650104&type=car&policy=1" title="行车路线">行车路线</a></li></ol><img src="/post/xj-north-circle/xj-img12.png" class=""><hr><h4 id="D10-10月6号-乌鲁木齐一日游"><a href="#D10-10月6号-乌鲁木齐一日游" class="headerlink" title="D10(10月6号):乌鲁木齐一日游"></a>D10(10月6号):乌鲁木齐一日游</h4><p>待定。。。。</p><hr><h4 id="D11-10月7号-乌鲁木齐一深圳"><a href="#D11-10月7号-乌鲁木齐一深圳" class="headerlink" title="D11(10月7号):乌鲁木齐一深圳"></a>D11(10月7号):乌鲁木齐一深圳</h4><p>乌鲁木齐—-飞–深圳</p><hr><h4 id="友情链接"><a href="#友情链接" class="headerlink" title="友情链接"></a>友情链接</h4><ol><li><p><a href="https://go.cqmmgo.com/forum-2466-thread-47141499934173209-1-1.html" title="【2017自驾游】有一种诗和远方叫新疆!北疆9日环线落地自驾游记">【2017自驾游】有一种诗和远方叫新疆!北疆9日环线落地自驾游记</a></p></li><li><p><a href="https://post.smzdm.com/p/779744/" title="说走就走的北疆自驾十日游(攻略+建议)">说走就走的北疆自驾十日游(攻略+建议)</a>;</p></li></ol>]]></content>
<categories>
<category> 旅行 </category>
</categories>
<tags>
<tag> 新疆 </tag>
<tag> 北疆 </tag>
</tags>
</entry>
<entry>
<title>健身运动</title>
<link href="//post/lifehealth.html"/>
<url>//post/lifehealth.html</url>
<content type="html"><![CDATA[<hr><p>健身圈从来就是一个强者的舞台,有的人通过健身强健了体魄,有的人通过健身找到了自信。正所谓“一入健身深似海”,健身就是有这样的魔力让你欲罢不能。</p><img src="/post/lifehealth/83b8000151b5571c9367.jpg" class="" title="img1"><span id="more"></span><h1 id="深蹲跳"><a href="#深蹲跳" class="headerlink" title="深蹲跳"></a>深蹲跳</h1><hr><p>锻炼部位:股四头肌、腘绳肌、臀大肌、腓肠肌。</p><img src="/post/lifehealth/1.gif" class="" title="avatar"><h1 id="俯卧撑"><a href="#俯卧撑" class="headerlink" title="俯卧撑"></a>俯卧撑</h1><hr><p>锻炼部位:胸大肌、肱三头肌。</p><img src="/post/lifehealth/2.gif" class="" title="avatar"><h1 id="开合跳"><a href="#开合跳" class="headerlink" title="开合跳"></a>开合跳</h1><hr><p>锻炼部位:股四头肌、三角肌、比目鱼肌、腓肠肌。</p><img src="/post/lifehealth/3.gif" class="" title="avatar"><h2 id="登山者"><a href="#登山者" class="headerlink" title="登山者"></a>登山者</h2><hr><p>锻炼部位:股四头肌、腘绳肌、胸肌。</p><img src="/post/lifehealth/4.gif" class="" title="avatar"><h1 id="波比跳"><a href="#波比跳" class="headerlink" title="波比跳"></a>波比跳</h1><hr><p>锻炼部位:股四头肌、三角肌、腹直肌。</p><img src="/post/lifehealth/5.gif" class="" title="avatar"><p>—贵在坚持—</p>]]></content>
<categories>
<category> 生活 </category>
</categories>
<tags>
<tag> 生活 </tag>
<tag> 运动 </tag>
</tags>
</entry>
<entry>
<title>树莓派3B(Raspberry 3B)搭建HomeAssistant</title>
<link href="//post/homeassistant.html"/>
<url>//post/homeassistant.html</url>
<content type="html"><![CDATA[<p>Home Assistant 是一款基于 Python 的智能家居开源系统,支持众多品牌的智能家居设备,可以轻松实现设备的语音控制、自动化等。本文档全站内容基于 Home Assistant 官方网站 本地化而成,具有以下特点:</p><h2 id="整合『组件』与『文档』页,采用更直观清晰、符合中文阅读的展现形式;剔除国内用户较少接触的组件说明,提高常用智能家居平台的层级和权重;跳出-Home-Assistant-原生框架,一并纳入-Floorplan、HADashboard-等相关衍生项目;本文将讲述树莓派3B搭建HomeAssistant和小米设备的接入。-一、系统要求和硬件配置"><a href="#整合『组件』与『文档』页,采用更直观清晰、符合中文阅读的展现形式;剔除国内用户较少接触的组件说明,提高常用智能家居平台的层级和权重;跳出-Home-Assistant-原生框架,一并纳入-Floorplan、HADashboard-等相关衍生项目;本文将讲述树莓派3B搭建HomeAssistant和小米设备的接入。-一、系统要求和硬件配置" class="headerlink" title="整合『组件』与『文档』页,采用更直观清晰、符合中文阅读的展现形式;剔除国内用户较少接触的组件说明,提高常用智能家居平台的层级和权重;跳出 Home Assistant 原生框架,一并纳入 Floorplan、HADashboard 等相关衍生项目;本文将讲述树莓派3B搭建HomeAssistant和小米设备的接入。# 一、系统要求和硬件配置"></a>整合『组件』与『文档』页,采用更直观清晰、符合中文阅读的展现形式;<br>剔除国内用户较少接触的组件说明,提高常用智能家居平台的层级和权重;<br>跳出 Home Assistant 原生框架,一并纳入 Floorplan、HADashboard 等相关衍生项目;<br>本文将讲述树莓派3B搭建HomeAssistant和小米设备的接入。<br><span id="more"></span><br># 一、系统要求和硬件配置</h2><ul><li>树莓派3B(Raspberry 3B);</li><li>一张16G的TF存储卡;</li><li>一台电脑(windowns or mac);</li><li>若干小米设备(小米网关、小米插座、小米吸顶灯等);</li><li>TF卡读卡器;</li><li>原生 <a href="https://www.raspberrypi.org/downloads/raspbian/">Raspbian</a> 系统;</li><li>xshell工具;</li><li><a href="http://www.upantool.com/hfxf/sd/3137.html">SDFormatter</a>;</li><li><a href="http://www.onlinedown.net/soft/110173.htm">Win32 Disk Imager</a>。</li><li><a href="http://www.pc6.com/mac/248733.html">Etcher Mac版</a>(MacOs下烧录工具);</li><li>Fing工具(Android端或者ios端都行)。</li></ul><h1 id="二、系统安装"><a href="#二、系统安装" class="headerlink" title="二、系统安装"></a>二、系统安装</h1><hr><ol><li>SDFormatter格式化TF存储卡</li><li>使用Win32 Disk Imager工具烧录Raspbian系统到TF卡</li><li>如果是在MacOs系统下,请用mac自带工具格式化TF卡,然后使用Etcher烧录系统;</li></ol><h1 id="三、树莓派配置"><a href="#三、树莓派配置" class="headerlink" title="三、树莓派配置"></a>三、树莓派配置</h1><hr><ol><li><p>烧录完毕后,TF卡自动命名为boot,<strong>在boot根目录新建ssh文件以便ss登录</strong>;</p></li><li><p>在TF卡根目录新建<code>wpa_supplicant.conf</code>文件,用于连接WiFi,配置如下:</p> <pre class="line-numbers language-none"><code class="language-none">country=CNctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdevupdate_config=1network={ ssid="路由器的ssid" psk="路由器的密码" key_mgmt=WPA-PSK priority=1}</code></pre></li><li><p>将TF卡插在树莓派后上电启动;</p></li><li><p>使用Fing查询树莓派的IP地址;</p></li><li><p>树莓派默认用户名<strong>pi</strong>,密码<strong>raspberry</strong>;</p></li><li><p>使用xshell连接树莓派,MacOs方式:<code>ssh [email protected] -p 22</code>;</p></li></ol><h2 id="3-1-启用root用户(由于本人天性爱自由,所以必须要绝对权限)"><a href="#3-1-启用root用户(由于本人天性爱自由,所以必须要绝对权限)" class="headerlink" title="3.1 启用root用户(由于本人天性爱自由,所以必须要绝对权限)"></a>3.1 启用root用户(由于本人天性爱自由,所以必须要绝对权限)</h2><ol><li>设置root用户密码</li></ol><blockquote><span class="custom-blockquote-svg"><svg width="24" height="24" viewBox="0 0 24 24" fill="" xmlns="http://www.w3.org/2000/svg" data-reactroot=""><path fill="" d="M22 12C22 6.5 17.5 2 12 2C6.5 2 2 6.5 2 12C2 17.5 6.5 22 12 22C13.8 22 15.5 21.5 17 20.6L22 22L20.7 17C21.5 15.5 22 13.8 22 12Z" undefined="1"></path><path fill="" d="M15.97 11.5H16.04C17.12 11.5 18 12.38 18 13.47V13.53C18 14.62 17.12 15.5 16.03 15.5H15.96C14.88 15.5 14 14.62 14 13.53V13.46C14 12.38 14.88 11.5 15.97 11.5Z" undefined="1"></path><path fill="" d="M7.97 11.5H8.04C9.12 11.5 10 12.38 10 13.47V13.53C10 14.62 9.12 15.5 8.03 15.5H7.97C6.88 15.5 6 14.62 6 13.53V13.46C6 12.38 6.88 11.5 7.97 11.5Z" undefined="1"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M17 8.5C15.23 8.97 14.07 10.84 14.01 13.27C14 13.33 14 13.4 14 13.47V13.5"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M9 8.5C7.23 8.97 6.07 10.84 6.01 13.27C6 13.33 6 13.4 6 13.47V13.5"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M15.97 11.5H16.04C17.12 11.5 18 12.38 18 13.47V13.53C18 14.62 17.12 15.5 16.03 15.5H15.96C14.88 15.5 14 14.62 14 13.53V13.46C14 12.38 14.88 11.5 15.97 11.5Z"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M7.97 11.5H8.04C9.12 11.5 10 12.38 10 13.47V13.53C10 14.62 9.12 15.5 8.03 15.5H7.97C6.88 15.5 6 14.62 6 13.53V13.46C6 12.38 6.88 11.5 7.97 11.5Z"></path></svg></span><p>sudo passwd root</p></blockquote><pre class="line-numbers language-none"><code class="language-none">pi@raspberrypi:~$ sudo passwd rootEnter new UNIX password: #输入第一遍密码Retype new UNIX password: #输入第二遍密码</code></pre><ol start="2"><li>启用 root 账号登录<blockquote><span class="custom-blockquote-svg"><svg width="24" height="24" viewBox="0 0 24 24" fill="" xmlns="http://www.w3.org/2000/svg" data-reactroot=""><path fill="" d="M22 12C22 6.5 17.5 2 12 2C6.5 2 2 6.5 2 12C2 17.5 6.5 22 12 22C13.8 22 15.5 21.5 17 20.6L22 22L20.7 17C21.5 15.5 22 13.8 22 12Z" undefined="1"></path><path fill="" d="M15.97 11.5H16.04C17.12 11.5 18 12.38 18 13.47V13.53C18 14.62 17.12 15.5 16.03 15.5H15.96C14.88 15.5 14 14.62 14 13.53V13.46C14 12.38 14.88 11.5 15.97 11.5Z" undefined="1"></path><path fill="" d="M7.97 11.5H8.04C9.12 11.5 10 12.38 10 13.47V13.53C10 14.62 9.12 15.5 8.03 15.5H7.97C6.88 15.5 6 14.62 6 13.53V13.46C6 12.38 6.88 11.5 7.97 11.5Z" undefined="1"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M17 8.5C15.23 8.97 14.07 10.84 14.01 13.27C14 13.33 14 13.4 14 13.47V13.5"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M9 8.5C7.23 8.97 6.07 10.84 6.01 13.27C6 13.33 6 13.4 6 13.47V13.5"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M15.97 11.5H16.04C17.12 11.5 18 12.38 18 13.47V13.53C18 14.62 17.12 15.5 16.03 15.5H15.96C14.88 15.5 14 14.62 14 13.53V13.46C14 12.38 14.88 11.5 15.97 11.5Z"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M7.97 11.5H8.04C9.12 11.5 10 12.38 10 13.47V13.53C10 14.62 9.12 15.5 8.03 15.5H7.97C6.88 15.5 6 14.62 6 13.53V13.46C6 12.38 6.88 11.5 7.97 11.5Z"></path></svg></span><p>sudo passwd –unlock root</p></blockquote></li></ol><pre class="line-numbers language-none"><code class="language-none">pi@raspberrypi:~$ sudo passwd --unlock rootpasswd: password expiry information changed.</code></pre><ol start="3"><li>设置root登陆</li></ol><blockquote><span class="custom-blockquote-svg"><svg width="24" height="24" viewBox="0 0 24 24" fill="" xmlns="http://www.w3.org/2000/svg" data-reactroot=""><path fill="" d="M22 12C22 6.5 17.5 2 12 2C6.5 2 2 6.5 2 12C2 17.5 6.5 22 12 22C13.8 22 15.5 21.5 17 20.6L22 22L20.7 17C21.5 15.5 22 13.8 22 12Z" undefined="1"></path><path fill="" d="M15.97 11.5H16.04C17.12 11.5 18 12.38 18 13.47V13.53C18 14.62 17.12 15.5 16.03 15.5H15.96C14.88 15.5 14 14.62 14 13.53V13.46C14 12.38 14.88 11.5 15.97 11.5Z" undefined="1"></path><path fill="" d="M7.97 11.5H8.04C9.12 11.5 10 12.38 10 13.47V13.53C10 14.62 9.12 15.5 8.03 15.5H7.97C6.88 15.5 6 14.62 6 13.53V13.46C6 12.38 6.88 11.5 7.97 11.5Z" undefined="1"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M17 8.5C15.23 8.97 14.07 10.84 14.01 13.27C14 13.33 14 13.4 14 13.47V13.5"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M9 8.5C7.23 8.97 6.07 10.84 6.01 13.27C6 13.33 6 13.4 6 13.47V13.5"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M15.97 11.5H16.04C17.12 11.5 18 12.38 18 13.47V13.53C18 14.62 17.12 15.5 16.03 15.5H15.96C14.88 15.5 14 14.62 14 13.53V13.46C14 12.38 14.88 11.5 15.97 11.5Z"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M7.97 11.5H8.04C9.12 11.5 10 12.38 10 13.47V13.53C10 14.62 9.12 15.5 8.03 15.5H7.97C6.88 15.5 6 14.62 6 13.53V13.46C6 12.38 6.88 11.5 7.97 11.5Z"></path></svg></span><p>sudo nano /etc/ssh/sshd_config </p></blockquote><pre class="line-numbers language-none"><code class="language-none">pi@raspberrypi:~$ sudo nano /etc/ssh/sshd_config </code></pre><blockquote><span class="custom-blockquote-svg"><svg width="24" height="24" viewBox="0 0 24 24" fill="" xmlns="http://www.w3.org/2000/svg" data-reactroot=""><path fill="" d="M22 12C22 6.5 17.5 2 12 2C6.5 2 2 6.5 2 12C2 17.5 6.5 22 12 22C13.8 22 15.5 21.5 17 20.6L22 22L20.7 17C21.5 15.5 22 13.8 22 12Z" undefined="1"></path><path fill="" d="M15.97 11.5H16.04C17.12 11.5 18 12.38 18 13.47V13.53C18 14.62 17.12 15.5 16.03 15.5H15.96C14.88 15.5 14 14.62 14 13.53V13.46C14 12.38 14.88 11.5 15.97 11.5Z" undefined="1"></path><path fill="" d="M7.97 11.5H8.04C9.12 11.5 10 12.38 10 13.47V13.53C10 14.62 9.12 15.5 8.03 15.5H7.97C6.88 15.5 6 14.62 6 13.53V13.46C6 12.38 6.88 11.5 7.97 11.5Z" undefined="1"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M17 8.5C15.23 8.97 14.07 10.84 14.01 13.27C14 13.33 14 13.4 14 13.47V13.5"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M9 8.5C7.23 8.97 6.07 10.84 6.01 13.27C6 13.33 6 13.4 6 13.47V13.5"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M15.97 11.5H16.04C17.12 11.5 18 12.38 18 13.47V13.53C18 14.62 17.12 15.5 16.03 15.5H15.96C14.88 15.5 14 14.62 14 13.53V13.46C14 12.38 14.88 11.5 15.97 11.5Z"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M7.97 11.5H8.04C9.12 11.5 10 12.38 10 13.47V13.53C10 14.62 9.12 15.5 8.03 15.5H7.97C6.88 15.5 6 14.62 6 13.53V13.46C6 12.38 6.88 11.5 7.97 11.5Z"></path></svg></span><p><code>Ctrl + W</code> 快捷键 搜索 <code>PermitRootLogin without-password</code><br>修改 <code>PermitRootLogin without-password</code> 为 <code>PermitRootLogin yes</code><br>执行完之后,用 <code>reboot</code> 命令重启,这样就可以解锁<code>root</code>账户。</p></blockquote><h1 id="四、HomeAssistant安装"><a href="#四、HomeAssistant安装" class="headerlink" title="四、HomeAssistant安装"></a>四、HomeAssistant安装</h1><hr><h2 id="4-1-源替换"><a href="#4-1-源替换" class="headerlink" title="4.1 源替换"></a>4.1 源替换</h2><p>由于默认都是从国外服务器下载安装,为了避免安装失败所以先替换成阿里的源。</p><ul><li><p>在此目录新建此文件:<code> ~/.pip/pip.conf</code></p></li><li><p>复制粘贴以下内容并保存:</p></li></ul><pre class="line-numbers language-none"><code class="language-none">[global]trusted-host=mirrors.aliyun.comindex-url=https://mirrors.aliyun.com/pypi/simple/</code></pre><h2 id="4-2-安装Python3"><a href="#4-2-安装Python3" class="headerlink" title="4.2 安装Python3"></a>4.2 安装Python3</h2><p>打开<code>Linux</code>系统命令行窗口,输入:<code>sudo apt-get install python3.5</code></p><p>应系统要求输入<code>root</code>账号的密码。</p><img src="/post/homeassistant/1.png" class="" title="img1"><p>安装资源准备好后提问是否继续安装,打回车确认。<br>然后等待安装完成。</p><img src="/post/homeassistant/2.png" class="" title="img1"><h2 id="4-3-安装Python3开发资源"><a href="#4-3-安装Python3开发资源" class="headerlink" title="4.3 安装Python3开发资源"></a>4.3 安装Python3开发资源</h2><p>在第一步安装完成后,继续输入命令:<code>sudo apt-get install python3.5-dev</code><br>在系统提问是否继续安装时打回车确认。<br>然后等待安装完成。</p><img src="/post/homeassistant/3.png" class="" title="img1"><img src="/post/homeassistant/4.png" class="" title="img1"><h2 id="4-4-安装Pip3"><a href="#4-4-安装Pip3" class="headerlink" title="4.4 安装Pip3"></a>4.4 安装Pip3</h2><p>继续在命令行中输入:<code>sudo apt install python3-pip</code><br>回车确认安装。<br>等待安装完成。</p><img src="/post/homeassistant/5.png" class="" title="img1"><h2 id="4-5-验证安装结果"><a href="#4-5-验证安装结果" class="headerlink" title="4.5 验证安装结果"></a>4.5 验证安装结果</h2><p>在命令行中输入<code>python3 --version</code>,看到显示版本。<br>在命令行中输入<code>pip3 --version</code>,看到显示版本。<br>说明Python3环境及Pip3工具安装成功。</p><img src="/post/homeassistant/6.png" class="" title="img1"><h2 id="4-6-使用Pip工具安装Home-Assistant"><a href="#4-6-使用Pip工具安装Home-Assistant" class="headerlink" title="4.6 使用Pip工具安装Home Assistant"></a>4.6 使用Pip工具安装Home Assistant</h2><p>在此步之前建议设置国内的安装源,可以提升后续的速度,参见这篇文档。<br>打开命令行窗口,输入:<code>sudo pip3 install homeassistant</code> (<font color="red">此步骤若失败,请重复操作</font>)<br>等待安装过程完成。</p><img src="/post/homeassistant/8.png" class="" title="img1"><h2 id="4-7-验证安装结果"><a href="#4-7-验证安装结果" class="headerlink" title="4.7 验证安装结果"></a>4.7 验证安装结果</h2><p>在命令行窗口,输入:<code>hass --debug</code> 参数<code>--debug</code>可以查看启动的日志。<br>首次启动需要初始化配置文件,也会自动下载一些所需的文件,会需要一些时间。有时因网络质量问题还会出现文件下载失败情况,导致启动过程受阻。此时可以关闭命令行窗口,再重新执行启动命令。</p><img src="/post/homeassistant/9.png" class="" title="img1"><p>继续等待启动过程完成,直到浏览器自动打开<code>Home Assistant</code>系统首页,即表明软件安装成功。</p><img src="/post/homeassistant/10.png" class="" title="img1"><h1 id="五、HomeAssistant设置自动启动"><a href="#五、HomeAssistant设置自动启动" class="headerlink" title="五、HomeAssistant设置自动启动"></a>五、HomeAssistant设置自动启动</h1><hr><p>Home Assistant 针对树莓派的发行版(手动安装除外)中都已经自带自启任务,其余系统安装的用户需要自行配置自启。</p><h2 id="5-1-配置自启动文件"><a href="#5-1-配置自启动文件" class="headerlink" title="5.1 配置自启动文件"></a>5.1 配置自启动文件</h2><p>如果你未使用 <code>Python</code> 虚拟环境安装 <code>Home Assistant</code>,请使用以下方法</p><pre><code>sudo nano -w /etc/systemd/system/[email protected]</code></pre><p>复制粘贴</p><pre><code>[Unit]Description=Home AssistantAfter=network-online.target[Service]Type=simpleUser=%iExecStart=/usr/local/bin/hass [Install]WantedBy=multi-user.target</code></pre><blockquote><span class="custom-blockquote-svg"><svg width="24" height="24" viewBox="0 0 24 24" fill="" xmlns="http://www.w3.org/2000/svg" data-reactroot=""><path fill="" d="M22 12C22 6.5 17.5 2 12 2C6.5 2 2 6.5 2 12C2 17.5 6.5 22 12 22C13.8 22 15.5 21.5 17 20.6L22 22L20.7 17C21.5 15.5 22 13.8 22 12Z" undefined="1"></path><path fill="" d="M15.97 11.5H16.04C17.12 11.5 18 12.38 18 13.47V13.53C18 14.62 17.12 15.5 16.03 15.5H15.96C14.88 15.5 14 14.62 14 13.53V13.46C14 12.38 14.88 11.5 15.97 11.5Z" undefined="1"></path><path fill="" d="M7.97 11.5H8.04C9.12 11.5 10 12.38 10 13.47V13.53C10 14.62 9.12 15.5 8.03 15.5H7.97C6.88 15.5 6 14.62 6 13.53V13.46C6 12.38 6.88 11.5 7.97 11.5Z" undefined="1"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M17 8.5C15.23 8.97 14.07 10.84 14.01 13.27C14 13.33 14 13.4 14 13.47V13.5"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M9 8.5C7.23 8.97 6.07 10.84 6.01 13.27C6 13.33 6 13.4 6 13.47V13.5"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M15.97 11.5H16.04C17.12 11.5 18 12.38 18 13.47V13.53C18 14.62 17.12 15.5 16.03 15.5H15.96C14.88 15.5 14 14.62 14 13.53V13.46C14 12.38 14.88 11.5 15.97 11.5Z"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M7.97 11.5H8.04C9.12 11.5 10 12.38 10 13.47V13.53C10 14.62 9.12 15.5 8.03 15.5H7.97C6.88 15.5 6 14.62 6 13.53V13.46C6 12.38 6.88 11.5 7.97 11.5Z"></path></svg></span><p>注意<code>ExecStart=/usr/local/bin/hass</code> 这个路径使用<code>whereis hass</code>查看路径</p></blockquote><h2 id="5-2-启动自启服务"><a href="#5-2-启动自启服务" class="headerlink" title="5.2 启动自启服务"></a>5.2 启动自启服务</h2><p>完成上述步骤后,请重新加载进程管理。</p><pre><code>sudo systemctl --system daemon-reload</code></pre><p>启用服务:</p><pre><code>sudo systemctl enable home-assistant@root</code></pre><h1 id="六、HomeAssistant的一些常用命令"><a href="#六、HomeAssistant的一些常用命令" class="headerlink" title="六、HomeAssistant的一些常用命令"></a>六、HomeAssistant的一些常用命令</h1><hr><h2 id="6-1-systemd相关的控制命令"><a href="#6-1-systemd相关的控制命令" class="headerlink" title="6.1 systemd相关的控制命令"></a>6.1 systemd相关的控制命令</h2><pre><code>sudo systemctl --system daemon-reload:重新加载systemd的配置文件。sudo systemctl enable home-assistant@root:设置home-assitant服务为自启动。sudo systemctl disable home-assistant@root:从自启动中去除home-assitant服务。sudo systemctl start home-assistant@root:手工启动home-assitant服务(命令中start可以替换成stop、restart、status,完成停止、重启、查看服务状态等功能)。sudo journalctl -f -u home-assistant@root:查看hass的日志输出。sudo journalctl -f -u home-assistant@[your user] | grep -i 'error':查看hass的日志输出中的error部分sudo systemctl restart home-assistant@root</code></pre><h2 id="6-2-使用脚本控制HomeAssistant"><a href="#6-2-使用脚本控制HomeAssistant" class="headerlink" title="6.2 使用脚本控制HomeAssistant"></a>6.2 使用脚本控制HomeAssistant</h2><pre><code>#!/bin/bashfunction check(){ echo "检查配置文件是否有错误" sudo hass --script check_config}function dis(){ echo "显示所有组件的配置信息" sudo hass --script check_config --info all}function hass(){ echo "启动hass" sudo systemctl start home-assistant@root}function rehass(){ echo "重启hass" sudo systemctl restart home-assistant@root}function stophass(){ echo "停止hass" sudo systemctl stop home-assistant@root}function log(){ echo "查看hass日志" sudo journalctl -f -u home-assistant@root}function debug(){ echo "debug hass" sudo hass --debug}echo "输入编号选择"echo "1. 检查配置文件是否有错误"echo "2. 显示所有组件的配置信息"echo "3. 启动hass"echo "4. 查看hass日志"echo "5. 重启hass"echo "6. 停止hass"echo "7. debug hass"echo "******Enter nothing to exit*****"read numcase "$num" in[1] ) (check);;[2] ) (dis);;[3] ) (hass);;[4] ) (log);;[5] ) (rehass);;[6] ) (stophass);;[7] ) (debug);;*) echo "nothing,exit";;esac</code></pre><h1 id="七、小米设备接入"><a href="#七、小米设备接入" class="headerlink" title="七、小米设备接入"></a>七、小米设备接入</h1><hr><ul><li><p>安装米家App(最新版本获取获取不到<code>Token</code>,使用【<a href="http://uuxia.cn:8123/file/com.xiaomi.smarthome.apk">MI Home5.0.19</a>】此版本OK);</p></li><li><p>使用<a href="http://uuxia.cn:8123/file/RE.apk">RE文件管理器</a>,打开<code>/data/data/com.xiaomi.smarthome/databases/miio2.db</code></p></li><li><p>记录设备的<code>token</code></p></li><li><p><a href="http://uuxia.cn:8123/file/configuration.yaml">configuration.yaml</a>配置文件</p></li></ul><h1 id="八、遇到的一些问题"><a href="#八、遇到的一些问题" class="headerlink" title="八、遇到的一些问题"></a>八、遇到的一些问题</h1><hr><ol><li>urllib3与chardet不兼容解决方案</li></ol><pre class="line-numbers language-none"><code class="language-none">pip3 uninstall urllib3pip3 uninstall chardetip3 install requests</code></pre><p>2.执行sh ./xxx.sh出现:“Syntax error: “(” unexpected”的解决方法</p><pre><code>sudo dpkg-reconfigure dash在选择项中选No,搞定了!</code></pre><ol start="3"><li>nodejs安装</li></ol><p><a href="https://blog.csdn.net/xiongtm/article/details/77620005">https://blog.csdn.net/xiongtm/article/details/77620005</a><br><a href="https://nodejs.org/dist/latest-v9.x/">https://nodejs.org/dist/latest-v9.x/</a></p>]]></content>
<categories>
<category> IoT </category>
</categories>
<tags>
<tag> IoT </tag>
<tag> HomeAssistant </tag>
</tags>
</entry>
<entry>
<title>Centos后台运行jar</title>
<link href="//post/centos-run-jar.html"/>
<url>//post/centos-run-jar.html</url>
<content type="html"><![CDATA[<p>jar后台运行</p><span id="more"></span><h1 id="jar后台运行"><a href="#jar后台运行" class="headerlink" title="jar后台运行"></a>jar后台运行</h1><pre><code>nohup java -jar xx.jar >/dev/null &</code></pre><blockquote><span class="custom-blockquote-svg"><svg width="24" height="24" viewBox="0 0 24 24" fill="" xmlns="http://www.w3.org/2000/svg" data-reactroot=""><path fill="" d="M22 12C22 6.5 17.5 2 12 2C6.5 2 2 6.5 2 12C2 17.5 6.5 22 12 22C13.8 22 15.5 21.5 17 20.6L22 22L20.7 17C21.5 15.5 22 13.8 22 12Z" undefined="1"></path><path fill="" d="M15.97 11.5H16.04C17.12 11.5 18 12.38 18 13.47V13.53C18 14.62 17.12 15.5 16.03 15.5H15.96C14.88 15.5 14 14.62 14 13.53V13.46C14 12.38 14.88 11.5 15.97 11.5Z" undefined="1"></path><path fill="" d="M7.97 11.5H8.04C9.12 11.5 10 12.38 10 13.47V13.53C10 14.62 9.12 15.5 8.03 15.5H7.97C6.88 15.5 6 14.62 6 13.53V13.46C6 12.38 6.88 11.5 7.97 11.5Z" undefined="1"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M17 8.5C15.23 8.97 14.07 10.84 14.01 13.27C14 13.33 14 13.4 14 13.47V13.5"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M9 8.5C7.23 8.97 6.07 10.84 6.01 13.27C6 13.33 6 13.4 6 13.47V13.5"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M15.97 11.5H16.04C17.12 11.5 18 12.38 18 13.47V13.53C18 14.62 17.12 15.5 16.03 15.5H15.96C14.88 15.5 14 14.62 14 13.53V13.46C14 12.38 14.88 11.5 15.97 11.5Z"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M7.97 11.5H8.04C9.12 11.5 10 12.38 10 13.47V13.53C10 14.62 9.12 15.5 8.03 15.5H7.97C6.88 15.5 6 14.62 6 13.53V13.46C6 12.38 6.88 11.5 7.97 11.5Z"></path></svg></span><p>此处的“>/dev/null”作用是将终端输出信息输出到空洞中,即不保存输出信息,若要查看输出信息需指定输出到那个文件,例如“>/xxx/yyy.out”</p></blockquote><h1 id="关闭后台进程"><a href="#关闭后台进程" class="headerlink" title="关闭后台进程"></a>关闭后台进程</h1><p>先查看后台进程pid</p><pre><code>ps -aux</code></pre><p>记住进程pid,然后kill命令关闭</p><pre><code>kill [pid]</code></pre>]]></content>
<categories>
<category> Centos </category>
</categories>
<tags>
<tag> Java </tag>
<tag> Jar </tag>
</tags>
</entry>
<entry>
<title>业余时间做什么,决定了你的生活品质</title>
<link href="//post/hobby.html"/>
<url>//post/hobby.html</url>
<content type="html"><![CDATA[<p>业余时间做什么,决定了你的生活品质</p><span id="more"></span><img src="/post/hobby/1.gif" class="" title="avatar"><h1 id="摄影"><a href="#摄影" class="headerlink" title="摄影"></a>摄影</h1><p>看到朋友晓川发布的一条动态,配的图特别有意思,以为他去哪里旅行了。</p><p>一问才知道,他拍的地方其实只是这座城市一条不起眼的街道。</p><p>不由感叹,自己怎么就从来没有发现,这条街道还有这样美的一面。</p><p>这或许得益于晓川的摄影素养,他总能从日常生活中,发现不平凡的景致,捕捉稍纵即逝的瞬间。</p><p>晓川说,一次偶然,他在某摄影论坛看到了一位摄影师的作品,内心深受触动。</p><p>从那以后,从入手第一部相机,到埋头理论书籍,再到拍下自己的第一万零一张照片,他在摄影的道路上一去不复返。</p><p>他用镜头记录岁月的流逝,也用这种方式感受生活的诗意和从容。</p><p>看晓川相册里的光影世界,无论是花叶建筑,还是人间世故,都能感受到他内心的丰富和细腻。</p><p>对摄影爱好的坚持,也让他的生活变得充实丰盈起来。</p><p>其实,摄影也好,绘画也好,拥有一些爱好,可以体验不一样的生活方式,不断探索生命的广度和深度。</p><p>王小波说,<strong>拥有自己的爱好,丰富的内心,再普通的日子也能过出妙趣横生,锦上添花般的诗意</strong>。</p><p>一个人只注重眼前是不够的,他还应该在生活常态之外,追求更诗意有趣的世界。</p><p>而爱好就是你表达自我的最好途径。</p><img src="/post/hobby/2.jpg" class="" title="img1"><h1 id="美食"><a href="#美食" class="headerlink" title="美食"></a>美食</h1><p>周末和几个朋友去赏桃花,时近正午,正有些饿了,小美拿出她亲手制作的提拉米苏蛋糕。</p><p>席地而坐后,小美还摘了一束粉紫色的野花,用养乐多瓶子插着,顿时感觉增色不少。</p><p>小美工作需要三班倒,平时非常忙。但无论如何,她都没有放弃对美食的追求。</p><p>休息时,她喜欢变着花样尝试制作不同的美食。</p><p>无论是精致的甜点,还是营养的羹汤,或者是可口的料理,她的手艺总能令人惊艳不已。</p><p>记得上次一个朋友过生日,小美为她制作了一个蛋糕,裱上了对方喜欢的花样。对方上传朋友圈后,获赞无数。</p><p>小美对美食的追求到了极致,有时为了买到最新鲜的食材,她会早起到市场采购。常常一顿饭菜下来,要花去不少时间精力。</p><p>但小美一点都没感觉到累,反而觉得这是一种调剂和享受。</p><p>当你专心去烹饪美食,并享受其中时,会感觉身边的一切都变得美好起来,仿佛世界都静止了。</p><p><strong>吃和思考,都是生命的必需品。</strong></p><p>作家朱利安·巴吉尼说,<strong>好好吃,就是好好生活。</strong></p><p>如果人明白美食真正的价值和本质,就会关注美食带来的生活状态。</p><p>美食也有很好的治愈功能,一个人有吃的念头,就有活的欲望。</p><p>喜欢美食的人,也通常能把生活过得热气腾腾。</p><p>因为他内心怀着对生活的热爱,一餐一饭,都讲究精致。</p><p>他会明白,什么才是生活的真实。</p><img src="/post/hobby/3.jpg" class="" title="img1"><h1 id="运动"><a href="#运动" class="headerlink" title="运动"></a>运动</h1><p>前段时间,表弟状态有些低迷,整日萎靡不振。</p><p>在别人的建议下,他开始跑步。</p><p>慢慢坚持下来后,他对待事物的态度开始变得积极,也喜欢上了这个运动。</p><p>表弟说,跑步时,我可以不受外界打扰,静下心来思考,反省自己。</p><p>有研究表明,人在快乐的时候,大脑会分泌一种叫做内啡肽的物质,而运动会加速这种物质的分泌。</p><p>一个坚持运动健身的人,往往也能做到自律、自爱,不会被欲望和情绪左右。</p><p>而以有益身心的运动消磨空闲时间的人,生活品质也不会太差。</p><img src="/post/hobby/4.jpg" class="" title="img1"><p>周国平曾说,<strong>排遣的方式,最能见出一个人的性情。</strong></p><p>有个朋友,闲暇时光喜欢尝试不同的东西:</p><p>比如背古诗文,觉得可以让自己内心沉静;</p><p>看各种纪录片,觉得这是了解世界最直观的方式;</p><p>还尝试学些入门的乐器,认为音乐给生活带来美好。</p><p>培养一些爱好,其实就是学会与自己相处,让一个人的生活变得有声有色。</p><p>或许有人认为,这些都是一些无用之事,谈不上兴趣爱好。</p><p>其实不然,<strong>有味之事,往往无用</strong>,并不是所有的爱好都要有用。</p><p>哪怕只是定期扔东西,整理房间,也是一种爱好。收拾房间能让心情变好,帮助你认识到什么才是想要的和值得追求的。</p><blockquote><span class="custom-blockquote-svg"><svg width="24" height="24" viewBox="0 0 24 24" fill="" xmlns="http://www.w3.org/2000/svg" data-reactroot=""><path fill="" d="M22 12C22 6.5 17.5 2 12 2C6.5 2 2 6.5 2 12C2 17.5 6.5 22 12 22C13.8 22 15.5 21.5 17 20.6L22 22L20.7 17C21.5 15.5 22 13.8 22 12Z" undefined="1"></path><path fill="" d="M15.97 11.5H16.04C17.12 11.5 18 12.38 18 13.47V13.53C18 14.62 17.12 15.5 16.03 15.5H15.96C14.88 15.5 14 14.62 14 13.53V13.46C14 12.38 14.88 11.5 15.97 11.5Z" undefined="1"></path><path fill="" d="M7.97 11.5H8.04C9.12 11.5 10 12.38 10 13.47V13.53C10 14.62 9.12 15.5 8.03 15.5H7.97C6.88 15.5 6 14.62 6 13.53V13.46C6 12.38 6.88 11.5 7.97 11.5Z" undefined="1"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M17 8.5C15.23 8.97 14.07 10.84 14.01 13.27C14 13.33 14 13.4 14 13.47V13.5"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M9 8.5C7.23 8.97 6.07 10.84 6.01 13.27C6 13.33 6 13.4 6 13.47V13.5"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M15.97 11.5H16.04C17.12 11.5 18 12.38 18 13.47V13.53C18 14.62 17.12 15.5 16.03 15.5H15.96C14.88 15.5 14 14.62 14 13.53V13.46C14 12.38 14.88 11.5 15.97 11.5Z"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M7.97 11.5H8.04C9.12 11.5 10 12.38 10 13.47V13.53C10 14.62 9.12 15.5 8.03 15.5H7.97C6.88 15.5 6 14.62 6 13.53V13.46C6 12.38 6.88 11.5 7.97 11.5Z"></path></svg></span><p><strong>正如梁文道所说:读一些无用的书,做一些无用的事,花一些无用的时间,都是为了在一切已知之外,保留一个超越自己的机会,人生中一些很了不起的变化,就是来自这种时刻。</strong></p></blockquote><p><strong>人生在世,总要找到一些专属于你的东西,才能让自己区别于其他人。</strong></p><p>如果没有兴趣爱好,就仅仅只是活着而已。</p><img src="/post/hobby/5.jpg" class="" title="img1"><h1 id="古人云"><a href="#古人云" class="headerlink" title="古人云"></a>古人云</h1><p>那些爱好广泛的人,其实是对这个世界保持好奇心。</p><p>精读君在终身成长词典《63:好奇》里提到:一个有好奇心的人,会思考云彩的形成与变换,会着迷于花蕾的初绽,觉察数学法则逻辑上的简洁性。</p><p>他会积极尝试不同事物,学习每一样新东西。</p><p>他会懂得欣赏一花一叶的美,也愿意尝试无用之事。</p><blockquote><span class="custom-blockquote-svg"><svg width="24" height="24" viewBox="0 0 24 24" fill="" xmlns="http://www.w3.org/2000/svg" data-reactroot=""><path fill="" d="M22 12C22 6.5 17.5 2 12 2C6.5 2 2 6.5 2 12C2 17.5 6.5 22 12 22C13.8 22 15.5 21.5 17 20.6L22 22L20.7 17C21.5 15.5 22 13.8 22 12Z" undefined="1"></path><path fill="" d="M15.97 11.5H16.04C17.12 11.5 18 12.38 18 13.47V13.53C18 14.62 17.12 15.5 16.03 15.5H15.96C14.88 15.5 14 14.62 14 13.53V13.46C14 12.38 14.88 11.5 15.97 11.5Z" undefined="1"></path><path fill="" d="M7.97 11.5H8.04C9.12 11.5 10 12.38 10 13.47V13.53C10 14.62 9.12 15.5 8.03 15.5H7.97C6.88 15.5 6 14.62 6 13.53V13.46C6 12.38 6.88 11.5 7.97 11.5Z" undefined="1"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M17 8.5C15.23 8.97 14.07 10.84 14.01 13.27C14 13.33 14 13.4 14 13.47V13.5"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M9 8.5C7.23 8.97 6.07 10.84 6.01 13.27C6 13.33 6 13.4 6 13.47V13.5"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M15.97 11.5H16.04C17.12 11.5 18 12.38 18 13.47V13.53C18 14.62 17.12 15.5 16.03 15.5H15.96C14.88 15.5 14 14.62 14 13.53V13.46C14 12.38 14.88 11.5 15.97 11.5Z"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M7.97 11.5H8.04C9.12 11.5 10 12.38 10 13.47V13.53C10 14.62 9.12 15.5 8.03 15.5H7.97C6.88 15.5 6 14.62 6 13.53V13.46C6 12.38 6.88 11.5 7.97 11.5Z"></path></svg></span><p>古人云,不为无益之事,何以遣有涯之生?</p></blockquote><p>你的爱好,就是你庸常生活的寄托,决定你的生活品质。</p>]]></content>
<categories>
<category> 生活 </category>
</categories>
<tags>
<tag> hobby </tag>
<tag> 生活 </tag>
</tags>
</entry>
<entry>
<title>L2TP/IPSec一键安装脚本</title>
<link href="//post/l2tp-ipsec-sh.html"/>
<url>//post/l2tp-ipsec-sh.html</url>
<content type="html"><![CDATA[<p>基于 OpenVZ 虚拟化技术的 VPS 需要开启TUN/TAP才能正常使用,购买 VPS 时请先咨询服务商是否支持开启 TUN/TAP。</p><p>OpenVZ 虚拟的 VPS 需要系统内核支持 IPSec 才行。也就是说,母服务器的内核如果不支持的话那就没办法,只能换 VPS。<br>因此,一般不建议在 OpenVZ 的 VPS 上安装本脚本。脚本如果检测到该 VPS 为 OpenVZ 架构,会出现警告提醒。</p><p>如何检测是否支持TUN模块?<br>执行命令:<br>cat /dev/net/tun<br>如果返回信息为:cat: /dev/net/tun: File descriptor in bad state 说明正常</p><p>如何检测是否支持ppp模块?<br>执行命令:<br>cat /dev/ppp<br>如果返回信息为:cat: /dev/ppp: No such device or address 说明正常<br>当然,脚本在安装时也会执行检查,如果不适用于安装,脚本会予以提示。</p><span id="more"></span><h2 id="本脚本适用环境:"><a href="#本脚本适用环境:" class="headerlink" title="本脚本适用环境:"></a>本脚本适用环境:</h2><p>系统支持:CentOS6+,Debian7+,Ubuntu12+<br>内存要求:≥128M<br><font color="red">更新日期:2017 年 05 月 28 日</font></p><h2 id="关于本脚本:"><a href="#关于本脚本:" class="headerlink" title="关于本脚本:"></a>关于本脚本:</h2><p>名词解释如下<br>L2TP(Layer 2 Tunneling Protocol)<br>IPSec(Internet Protocol Security)<br>IKEv2 (Internet Key Exchange v2)<br>能实现 IPsec 的目前总体上有 openswan,libreswan,strongswan 这3种。<br>libreswan 是基于 openswan 的 fork,所以现在各个发行版基本已经看不到 openswan 的身影了。<br>当然也有使用 strongswan 的。</p><p>之所以要更新 L2TP 一键安装脚本,是因为随着各个 Linux 发行版不断推陈出新,原有的脚本已经不适应现在的需求。<br>本脚本通过编译安装最新版 libreswan 来实现 IPSec(CentOS7 下则是全部 yum 安装),yum 或 apt-get 来安装 xl2tpd,再根据各个发行版的使用方法不同,部署防火墙规则。</p><h2 id="1-使用方法:"><a href="#1-使用方法:" class="headerlink" title="1. 使用方法:"></a><font color="red">1. 使用方法:</font></h2><p>root 用户登录后,运行以下命令:</p><pre class="line-numbers language-none"><code class="language-none">wget --no-check-certificate https://raw.githubusercontent.com/teddysun/across/master/l2tp.shchmod +x l2tp.sh./l2tp.sh</code></pre><p>执行后,会有如下交互界面</p><img src="/post/l2tp-ipsec-sh/l2tp_1.png" class="" title="img1"><p>Please input IP-Range:<br>(Default Range: 192.168.18):<br>输入本地IP段范围(本地电脑连接到VPS后给分配的一个本地IP地址),直接回车意味着输入默认值192.168.18</p><p>Please input PSK:<br>(Default PSK: teddysun.com):<br>PSK意为预共享密钥,即指定一个密钥将来在连接时需要用到,直接回车意味着输入默认值teddysun.com</p><p>Please input Username:<br>(Default Username: teddysun):<br>Username意为用户名,即第一个默认用户。直接回车意味着输入默认值teddysun</p><p>Please input teddysun’s password:<br>(Default Password: Q4SKhu2EXQ):<br>输入用户的密码,默认会随机生成一个10位包含大小写字母和数字的密码,当然你也可以指定密码。</p><p>ServerIP:your_server_main_IP<br>显示你的 VPS 的主 IP(如果是多 IP 的 VPS 也只显示一个)</p><p>Server Local IP:192.168.18.1<br>显示你的 VPS 的本地 IP(默认即可)</p><p>Client Remote IP Range:192.168.18.2-192.168.18.254<br>显示 IP 段范围</p><p>PSK:teddysun.com<br>显示 PSK</p><p>Press any key to start…or Press Ctrl+c to cancel<br>按下任意按键继续,如果想取消安装,请按Ctrl+c键</p><p>安装完成后,脚本会执行 ipsec verify 命令并提示如下:</p><pre class="line-numbers language-none"><code class="language-none">If there are no [FAILED] above, then you can connect to yourL2TP VPN Server with the default Username/Password is below:ServerIP:your_server_IPPSK:your PSKUsername:your usenamePassword:your passwordIf you want to modify user settings, please use command(s):l2tp -a (Add a user)l2tp -d (Delete a user)l2tp -l (List all users)l2tp -m (Modify a user password)Welcome to visit https://teddysun.com/448.htmlEnjoy it!</code></pre><p>如果你要想对用户进行操作,可以使用如下命令:<br>l2tp -a 新增用户<br>l2tp -d 删除用户<br>l2tp -m 修改现有的用户的密码<br>l2tp -l 列出所有用户名和密码<br>l2tp -h 列出帮助信息</p><h2 id="2-注意事项:"><a href="#2-注意事项:" class="headerlink" title="2. 注意事项:"></a><font color="red">2. 注意事项:</font></h2><p>1、错误809:<br>解决:路由线路上有防火墙没有关闭(pptp穿透防火墙的能力较差)<br>2、错误代码619<br>解决:</p><pre class="line-numbers language-none"><code class="language-none">rm -r /dev/pppmknod /dev/ppp c 108 0 然后重启VPS即可。</code></pre><p>如果还未解决,尝试重启机器。</p><p>3、要根据ppp的版本来选择对应的pptpd版本。<br>ppp-2.4.4 对应 pptpd-1.3.4<br>ppp-2.4.5 对应 pptpd-1.4.0</p><h2 id="3-其他事项:"><a href="#3-其他事项:" class="headerlink" title="3. 其他事项:"></a><font color="red">3. 其他事项:</font></h2><p>1、脚本在安装完成后,已自动启动进程,并加入了开机自启动。<br>2、脚本会改写 iptables 或 firewalld 的规则。<br>3、脚本安装时,会即时将安装日志写到 /root/l2tp.log 文件里,如果你安装失败,可以通过此文件来寻找错误信息。</p><h2 id="4-使用命令:"><a href="#4-使用命令:" class="headerlink" title="4. 使用命令:"></a><font color="red">4. 使用命令:</font></h2><p>ipsec status (查看 IPSec 运行状态)<br>ipsec verify (查看 IPSec 检查结果)<br>/etc/init.d/ipsec start|stop|restart|status (CentOS6 下使用)<br>/etc/init.d/xl2tpd start|stop|restart (CentOS6 下使用)<br>systemctl start|stop|restart|status ipsec (CentOS7 下使用)<br>systemctl start|stop|restart xl2tpd (CentOS7 下使用)<br>service ipsec start|stop|restart|status (Debian/Ubuntu 下使用)<br>service xl2tpd start|stop|restart (Debian/Ubuntu 下使用)</p><h2 id="5-更新日志"><a href="#5-更新日志" class="headerlink" title="5. 更新日志"></a><font color="red">5. 更新日志</font></h2><p>2017 年 05 月 28 日:<br>升级 libreswan 到版本 3.20。<br>修正 libreswan 的若干配置问题。<br>修正 xl2tpd 的端口监听配置问题。<br>修正在 CentOS 6 对 libevent2 的依赖问题,改为 yum 安装 libevent2-devel。<br>测试表明,在内网环境的 VPS 里(如AWS, IDCF,GCE,腾讯云,阿里云等)也可以正常使用了。</p><p><font color="red">2017 年 02 月 25 日:</font><br>升级 libreswan 到版本 3.19。</p><p><font color="red">2016 年 09 月 12 日:</font><br>修正了在 CentOS 6 下 libevent2 依赖的问题;<br>新增了一个 -m 选项,用以修改现有用户的密码。</p><p><font color="red">2016 年 08 月 13 日:</font><br>修正 Debian 8 下的 sd-daemon.h: No such file or directory 问题,是由于缺少依赖包 libsystemd-daemon-dev 导致的。</p><p><font color="red">2016 年 08 月 05 日:</font><br>升级 libreswan 到版本 3.18。</p><p><font color="red">2016 年 06 月 10 日:</font><br>脚本在安装完成后,新增了几个命令,便于操作用户<br>l2tp -a 新增用户<br>l2tp -d 删除用户<br>l2tp -l 列出所有用户<br>l2tp -h 列出帮助信息</p><p>参考链接:<br><a href="https://libreswan.org/wiki/3.14_on_Debian_Wheezy">https://libreswan.org/wiki/3.14_on_Debian_Wheezy</a><br><a href="https://github.com/libreswan/libreswan">https://github.com/libreswan/libreswan</a></p>]]></content>
<categories>
<category> VPN </category>
</categories>
<tags>
<tag> shadowsocks </tag>
<tag> 科学上网 </tag>
</tags>
</entry>
<entry>
<title>Android导入第三方静态库.a编译成动态库.so</title>
<link href="//post/android-ndk-so-a.html"/>
<url>//post/android-ndk-so-a.html</url>
<content type="html"><![CDATA[<p>Android导入第三方静态库.a编译成动态库.so</p><span id="more"></span><img src="/post/android-ndk-so-a/img1.png" class="" title="img1"><p>下面我以一个简单的实际例子来讲解如何在动态库中导入静态库。</p><p>静态库中的源代码有两个文件:static.h, static.c,有一个add方法 static.h</p><pre class="line-numbers language-c++" data-language="c++"><code class="language-c++">#include <stdio.h> int add(int x, int y);static.c#include "static.h" int add(int x, int y) { return x + y; }</code></pre><p>将它编译成静态库,Android.mk如下:</p><pre class="line-numbers language-none"><code class="language-none">LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := static_add LOCAL_SRC_FILES := static.c include $(BUILD_STATIC_LIBRARY)</code></pre><p>注意编译静态库的时候,必须有一个Application.mk文件:</p><blockquote><span class="custom-blockquote-svg"><svg width="24" height="24" viewBox="0 0 24 24" fill="" xmlns="http://www.w3.org/2000/svg" data-reactroot=""><path fill="" d="M22 12C22 6.5 17.5 2 12 2C6.5 2 2 6.5 2 12C2 17.5 6.5 22 12 22C13.8 22 15.5 21.5 17 20.6L22 22L20.7 17C21.5 15.5 22 13.8 22 12Z" undefined="1"></path><path fill="" d="M15.97 11.5H16.04C17.12 11.5 18 12.38 18 13.47V13.53C18 14.62 17.12 15.5 16.03 15.5H15.96C14.88 15.5 14 14.62 14 13.53V13.46C14 12.38 14.88 11.5 15.97 11.5Z" undefined="1"></path><path fill="" d="M7.97 11.5H8.04C9.12 11.5 10 12.38 10 13.47V13.53C10 14.62 9.12 15.5 8.03 15.5H7.97C6.88 15.5 6 14.62 6 13.53V13.46C6 12.38 6.88 11.5 7.97 11.5Z" undefined="1"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M17 8.5C15.23 8.97 14.07 10.84 14.01 13.27C14 13.33 14 13.4 14 13.47V13.5"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M9 8.5C7.23 8.97 6.07 10.84 6.01 13.27C6 13.33 6 13.4 6 13.47V13.5"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M15.97 11.5H16.04C17.12 11.5 18 12.38 18 13.47V13.53C18 14.62 17.12 15.5 16.03 15.5H15.96C14.88 15.5 14 14.62 14 13.53V13.46C14 12.38 14.88 11.5 15.97 11.5Z"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M7.97 11.5H8.04C9.12 11.5 10 12.38 10 13.47V13.53C10 14.62 9.12 15.5 8.03 15.5H7.97C6.88 15.5 6 14.62 6 13.53V13.46C6 12.38 6.88 11.5 7.97 11.5Z"></path></svg></span><p>APP_MODULES:=static_add</p></blockquote><p>APP_MODULES的值应该和Android.mk中的LOCAL_MODULE的值保持一样。</p><p>然后调用ndk-build进行编译生成libstatic_add.a静态库</p><pre class="line-numbers language-none"><code class="language-none">hejinlai_iMac:jni hejinlai$ ndk-buildPrebuilt : libstatic_add.a <= jni/ 生成静态库后,然后编写动态库中的源代码: share.h share.c share.h [cpp]#include int test_add(int x, int y);share.c1234567 #include “share.h”#include “static.h”int test_add(int x, int y){// 调用static里面的方法return add(x, y);}</code></pre><p>编写导入静态库的Android.mk:</p><pre class="line-numbers language-none"><code class="language-none">LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := static_add LOCAL_SRC_FILES := libstatic_add.a include $(PREBUILT_STATIC_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := share_add LOCAL_STATIC_LIBRARIES := static_add LOCAL_SRC_FILES := share.c include $(BUILD_SHARED_LIBRARY)</code></pre><p>注意上面生成的libstatic_add.a必须跟Android.mk放在同一目录下,否则需要填写相应的路径,然后进行编译:</p><pre class="line-numbers language-none"><code class="language-none">hejinlai_iMac:jni hejinlai$ ndk-buildCompile thumb : share_add <= share.c Prebuilt : libstatic_add.a <= jni/ SharedLibrary : libshare_add.so Install : libshare_add.so => libs/armeabi/libshare_add.so</code></pre><p>提示so编译成功。</p><p>需要注意的是我这边share.c和static.c放在同一目录下,如果放在不同的目录下,需要指定</p><p>LOCAL_C_INCLUDES链接到相应的路径。</p>]]></content>
<categories>
<category> Android </category>
</categories>
<tags>
<tag> Andorid </tag>
<tag> ndk </tag>
<tag> so </tag>
<tag> a </tag>
</tags>
</entry>
<entry>
<title>喜马拉雅WiFi音响绑定及通讯协议初稿</title>
<link href="//post/ximalaya.html"/>
<url>//post/ximalaya.html</url>
<content type="html"><![CDATA[<p>喜马拉雅WiFi音响绑定及通讯协议初稿</p><span id="more"></span><h1 id="通讯协议"><a href="#通讯协议" class="headerlink" title="通讯协议"></a><strong>通讯协议</strong></h1><table><thead><tr><th align="left">0x5A</th><th align="left">数据长度</th><th align="left">框架版本</th><th align="left">协议类型</th><th align="left">设备编码</th><th align="left">Mac地址</th><th align="left">数据帧序列号</th><th align="left">保留字</th><th align="left">数据类型</th><th align="left">数据内容</th><th align="left">检验码FCS</th></tr></thead><tbody><tr><td align="left">1字节</td><td align="left">2字节</td><td align="left">1字节</td><td align="left">1字节</td><td align="left">8字节</td><td align="left">6字节</td><td align="left">4字节</td><td align="left">8字节</td><td align="left">2字节</td><td align="left">N字节</td><td align="left">2字节</td></tr></tbody></table><h1 id="通讯Json格式:"><a href="#通讯Json格式:" class="headerlink" title="通讯Json格式:"></a><strong>通讯Json格式</strong>:</h1><pre><code>{ "cmd": 0 ,//命令码"code": 0,//返回码"msg": "",//状态消息"data": ......//数据节点}</code></pre><h2 id="参数说明"><a href="#参数说明" class="headerlink" title="参数说明"></a><strong>参数说明</strong></h2><table><thead><tr><th align="left">参数名称</th><th align="left">是否必须</th><th align="left">字段类型</th><th align="left">参数说明</th></tr></thead><tbody><tr><td align="left">cmd</td><td align="left">YES</td><td align="left">int</td><td align="left">命令码</td></tr><tr><td align="left">code</td><td align="left">NO</td><td align="left">int</td><td align="left">返回码</td></tr><tr><td align="left">msg</td><td align="left">NO</td><td align="left">String</td><td align="left">状态消息</td></tr><tr><td align="left">data</td><td align="left">NO</td><td align="left">String</td><td align="left">数据节点</td></tr></tbody></table><h2 id="全局命令码"><a href="#全局命令码" class="headerlink" title="全局命令码"></a><strong>全局命令码</strong></h2><blockquote><span class="custom-blockquote-svg"><svg width="24" height="24" viewBox="0 0 24 24" fill="" xmlns="http://www.w3.org/2000/svg" data-reactroot=""><path fill="" d="M22 12C22 6.5 17.5 2 12 2C6.5 2 2 6.5 2 12C2 17.5 6.5 22 12 22C13.8 22 15.5 21.5 17 20.6L22 22L20.7 17C21.5 15.5 22 13.8 22 12Z" undefined="1"></path><path fill="" d="M15.97 11.5H16.04C17.12 11.5 18 12.38 18 13.47V13.53C18 14.62 17.12 15.5 16.03 15.5H15.96C14.88 15.5 14 14.62 14 13.53V13.46C14 12.38 14.88 11.5 15.97 11.5Z" undefined="1"></path><path fill="" d="M7.97 11.5H8.04C9.12 11.5 10 12.38 10 13.47V13.53C10 14.62 9.12 15.5 8.03 15.5H7.97C6.88 15.5 6 14.62 6 13.53V13.46C6 12.38 6.88 11.5 7.97 11.5Z" undefined="1"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M17 8.5C15.23 8.97 14.07 10.84 14.01 13.27C14 13.33 14 13.4 14 13.47V13.5"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M9 8.5C7.23 8.97 6.07 10.84 6.01 13.27C6 13.33 6 13.4 6 13.47V13.5"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M15.97 11.5H16.04C17.12 11.5 18 12.38 18 13.47V13.53C18 14.62 17.12 15.5 16.03 15.5H15.96C14.88 15.5 14 14.62 14 13.53V13.46C14 12.38 14.88 11.5 15.97 11.5Z"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M7.97 11.5H8.04C9.12 11.5 10 12.38 10 13.47V13.53C10 14.62 9.12 15.5 8.03 15.5H7.97C6.88 15.5 6 14.62 6 13.53V13.46C6 12.38 6.88 11.5 7.97 11.5Z"></path></svg></span><p>每一种操作对用一个命令码,用作标识指令。</p></blockquote><h4 id="全局命令码说明如下:"><a href="#全局命令码说明如下:" class="headerlink" title="全局命令码说明如下:"></a>全局命令码说明如下:</h4><table><thead><tr><th align="left">命令码(十六进制)</th><th align="left">十进制</th><th align="left">说明</th></tr></thead><tbody><tr><td align="left">0x0001</td><td align="left">1</td><td align="left">添加歌曲</td></tr><tr><td align="left">0x0002</td><td align="left">2</td><td align="left">App查询歌曲列表</td></tr><tr><td align="left">0x0003</td><td align="left">3</td><td align="left">升级操作</td></tr><tr><td align="left">0x0004</td><td align="left">4</td><td align="left">播放</td></tr><tr><td align="left">0x0005</td><td align="left">5</td><td align="left">关机</td></tr><tr><td align="left">0x0006</td><td align="left">6</td><td align="left">静音/解除静音</td></tr><tr><td align="left">0x0007</td><td align="left">7</td><td align="left">音量+</td></tr><tr><td align="left">0x0008</td><td align="left">8</td><td align="left">音量-</td></tr><tr><td align="left">0x0009</td><td align="left">9</td><td align="left">切换aux状态</td></tr><tr><td align="left">0x000a</td><td align="left">10</td><td align="left">下一曲</td></tr><tr><td align="left">0x000b</td><td align="left">11</td><td align="left">上一曲</td></tr><tr><td align="left">0x000c</td><td align="left">12</td><td align="left">暂停</td></tr><tr><td align="left">0x000d</td><td align="left">13</td><td align="left">App查询播放状态</td></tr><tr><td align="left">0x000e</td><td align="left">14</td><td align="left">WIFI 无线简易连接</td></tr><tr><td align="left">0x000f</td><td align="left">15</td><td align="left">设备回复心跳</td></tr><tr><td align="left">0x400f</td><td align="left">16399</td><td align="left">App发送心跳</td></tr><tr><td align="left">0x0011</td><td align="left">17</td><td align="left">palyMode(顺序播放/随机播放/列表循环/单曲循环/)</td></tr><tr><td align="left">0x0012</td><td align="left">18</td><td align="left">音量设置(直接设置音量值)</td></tr><tr><td align="left">0x0013</td><td align="left">19</td><td align="left">设备推送播放状态</td></tr><tr><td align="left">0x0014</td><td align="left">20</td><td align="left">设备推送播放列表</td></tr><tr><td align="left">0x0015</td><td align="left">21</td><td align="left">拖拽进度条</td></tr></tbody></table><h2 id="全局返回码"><a href="#全局返回码" class="headerlink" title="全局返回码"></a><strong>全局返回码</strong></h2><blockquote><span class="custom-blockquote-svg"><svg width="24" height="24" viewBox="0 0 24 24" fill="" xmlns="http://www.w3.org/2000/svg" data-reactroot=""><path fill="" d="M22 12C22 6.5 17.5 2 12 2C6.5 2 2 6.5 2 12C2 17.5 6.5 22 12 22C13.8 22 15.5 21.5 17 20.6L22 22L20.7 17C21.5 15.5 22 13.8 22 12Z" undefined="1"></path><path fill="" d="M15.97 11.5H16.04C17.12 11.5 18 12.38 18 13.47V13.53C18 14.62 17.12 15.5 16.03 15.5H15.96C14.88 15.5 14 14.62 14 13.53V13.46C14 12.38 14.88 11.5 15.97 11.5Z" undefined="1"></path><path fill="" d="M7.97 11.5H8.04C9.12 11.5 10 12.38 10 13.47V13.53C10 14.62 9.12 15.5 8.03 15.5H7.97C6.88 15.5 6 14.62 6 13.53V13.46C6 12.38 6.88 11.5 7.97 11.5Z" undefined="1"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M17 8.5C15.23 8.97 14.07 10.84 14.01 13.27C14 13.33 14 13.4 14 13.47V13.5"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M9 8.5C7.23 8.97 6.07 10.84 6.01 13.27C6 13.33 6 13.4 6 13.47V13.5"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M15.97 11.5H16.04C17.12 11.5 18 12.38 18 13.47V13.53C18 14.62 17.12 15.5 16.03 15.5H15.96C14.88 15.5 14 14.62 14 13.53V13.46C14 12.38 14.88 11.5 15.97 11.5Z"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M7.97 11.5H8.04C9.12 11.5 10 12.38 10 13.47V13.53C10 14.62 9.12 15.5 8.03 15.5H7.97C6.88 15.5 6 14.62 6 13.53V13.46C6 12.38 6.88 11.5 7.97 11.5Z"></path></svg></span><p>每次调用接口时,可能获得正确或错误的返回码,可以根据返回码信息调试接口,排查错误。<br>####全局返回码说明如下:</p><table><thead><tr><th align="left">0</th><th align="left">请求成功</th></tr></thead><tbody><tr><td align="left">200</td><td align="left">无错误</td></tr><tr><td align="left">400</td><td align="left">不支持此接口</td></tr><tr><td align="left">401</td><td align="left">JSON数据解析错误</td></tr></tbody></table></blockquote><h2 id="示例"><a href="#示例" class="headerlink" title="示例"></a><strong>示例</strong></h2><h3 id="字符串"><a href="#字符串" class="headerlink" title="字符串"></a><strong>字符串</strong></h3><pre><code>{ "cmd": 0x0001 ,//命令码"code": 0, //返回码"msg": "", //状态消息"data": "This is string" //数据节点}</code></pre><h3 id="整形参数"><a href="#整形参数" class="headerlink" title="整形参数"></a><strong>整形参数</strong></h3><pre><code>{ "cmd": 0x0001 ,//命令码"code": 0, //返回码"msg": "", //状态消息"data": 1 //数据节点}</code></pre><h3 id="对象"><a href="#对象" class="headerlink" title="对象"></a><strong>对象</strong></h3><pre><code>{ "cmd": 0x0001 ,//命令码"code": 0, //返回码"msg": "", //状态消息"data": { "ssid":"TP-link", //连接的路由名称 "password":"12345678", //路由密码,需要加密 } }</code></pre><h3 id="数组"><a href="#数组" class="headerlink" title="数组"></a><strong>数组</strong></h3><pre><code>{ "cmd": 0x001 ,//命令码"code": 0, //返回码"msg": "", //状态消息"data":[ { "id" : "0" "name" : “xxxx", "artist" : “xxxx", "album_title": “xxxx", "cover_url_small”:“xxxx", "cover_url_middle":"xxxx", "cover_url_large":"xxxx", "url":"xxxxxxxxx" {详细规格见规格说明url部分}, }, { "id":"1" "name":"xxxx1", "artist":"xxxx1", "album":"xxxx1", "cover_url_small":"xxxx", "cover_url_middle":"xxxx", "cover_url_large":"xxxx", "url":"xxxxxxxxxx"{详细规格见规格说明url部分}, } ]}</code></pre><h2 id="指令说明"><a href="#指令说明" class="headerlink" title="指令说明"></a><strong>指令说明</strong></h2><h3 id="一、设备基础指令"><a href="#一、设备基础指令" class="headerlink" title="一、设备基础指令"></a><strong>一、设备基础指令</strong></h3><ol><li><strong>App扫描设备</strong></li></ol><table><thead><tr><th align="left">0x5A</th><th align="left">数据长度</th><th align="left">框架版本</th><th align="left">协议类型</th><th align="left">设备编码</th><th align="left">Mac地址</th><th align="left">数据帧序列号</th><th align="left">保留字</th><th align="left">数据类型</th><th align="left">数据内容</th><th align="left">检验码FCS</th></tr></thead><tbody><tr><td align="left">5A</td><td align="left">0022</td><td align="left">40</td><td align="left">01</td><td align="left">0000000000000000</td><td align="left">000000000000</td><td align="left">20000000</td><td align="left">0000000000000000</td><td align="left">0405</td><td align="left">data</td><td align="left">381a</td></tr></tbody></table><ul><li><font color="#c00"><strong>命令字:0x0405</strong></font></li><li><font color="#c00"><strong>data区:NULL</strong></font></li></ul><ol start="2"><li><strong>设备回复自身信息</strong></li></ol><table><thead><tr><th align="left">0x5A</th><th align="left">数据长度</th><th align="left">框架版本</th><th align="left">协议类型</th><th align="left">设备编码</th><th align="left">Mac地址</th><th align="left">数据帧序列号</th><th align="left">保留字</th><th align="left">数据类型</th><th align="left">数据内容</th><th align="left">检验码FCS</th></tr></thead><tbody><tr><td align="left">5A</td><td align="left">xxxx</td><td align="left">40</td><td align="left">01</td><td align="left">00000199001b0300</td><td align="left">d8f710e019b0</td><td align="left">00000000</td><td align="left">0000000000000000</td><td align="left">0305</td><td align="left">data</td><td align="left">xxxx</td></tr></tbody></table><ul><li><font color="#c00"><strong>命令字:0x0305</strong></font></li><li><font color="#c00"><strong>厂商ID:0x0199</strong> </font></li><li><font color="#c00"><strong>大分类:0x1b</strong> </font></li><li><font color="#c00"><strong>小分类:0x03</strong></font></li></ul><ol start="3"><li><strong>App发送心跳包</strong></li></ol><table><thead><tr><th align="left">0x5A</th><th align="left">数据长度</th><th align="left">框架版本</th><th align="left">协议类型</th><th align="left">设备编码</th><th align="left">Mac地址</th><th align="left">数据帧序列号</th><th align="left">保留字</th><th align="left">数据类型</th><th align="left">数据内容</th><th align="left">检验码FCS</th></tr></thead><tbody><tr><td align="left">5A</td><td align="left">xxxx</td><td align="left">40</td><td align="left">01</td><td align="left">0000000000000000</td><td align="left">000000000000</td><td align="left">20000000</td><td align="left">0000000000000000</td><td align="left">0104</td><td align="left">data</td><td align="left">xxxx</td></tr></tbody></table><ul><li><font color="#c00"><strong>命令字:0x0104</strong></font></li><li><font color="#c00"><strong>data区:json</strong></font></li></ul><p>示例:</p><pre><code> { "cmd": 0x400f ,//命令码 "code": 0,//返回码 "msg": "",//状态消息 "data": ......//数据节点 }</code></pre><ol start="4"><li><strong>设备回复心跳</strong></li></ol><table><thead><tr><th align="left">0x5A</th><th align="left">数据长度</th><th align="left">框架版本</th><th align="left">协议类型</th><th align="left">设备编码</th><th align="left">Mac地址</th><th align="left">数据帧序列号</th><th align="left">保留字</th><th align="left">数据类型</th><th align="left">数据内容</th><th align="left">检验码FCS</th></tr></thead><tbody><tr><td align="left">5A</td><td align="left">xxxx</td><td align="left">40</td><td align="left">01</td><td align="left">0000000000000000</td><td align="left">000000000000</td><td align="left">00000000</td><td align="left">0000000000000000</td><td align="left">0204</td><td align="left">data</td><td align="left">xxxx</td></tr></tbody></table><ul><li><font color="#c00"> <strong>命令字:0x0204</strong></font> </li><li><font color="#c00"> <strong>data区:json</strong></font></li></ul><p>示例:</p><pre><code> { "cmd": 0x000f ,//命令码 "code": 0,//返回码 "msg": "",//状态消息 "data": { "deviceId": "SPK设备序列号" } }</code></pre><h3 id="二、App主动控制终端指令"><a href="#二、App主动控制终端指令" class="headerlink" title="二、App主动控制终端指令"></a><strong>二、App主动控制终端指令</strong></h3><p><strong>1.App控制终端</strong></p><table><thead><tr><th align="left">0x5A</th><th align="left">数据长度</th><th align="left">框架版本</th><th align="left">协议类型</th><th align="left">设备编码</th><th align="left">Mac地址</th><th align="left">数据帧序列号</th><th align="left">保留字</th><th align="left">数据类型</th><th align="left">数据内容</th><th align="left">检验码FCS</th></tr></thead><tbody><tr><td align="left">5A</td><td align="left">xxxx</td><td align="left">40</td><td align="left">01</td><td align="left">0000000000000000</td><td align="left">000000000000</td><td align="left">00000000</td><td align="left">0000000000000000</td><td align="left">0104</td><td align="left">data</td><td align="left">xxxx</td></tr></tbody></table><ul><li><font color="#c00"> <strong>命令字:0x0104</strong></font> </li><li><font color="#c00"> <strong>data区:json数据</strong></font></li></ul><p>示例:</p><pre><code> { "cmd": 0x00xx ,//命令码 "code": 0,//返回码 "msg": "",//状态消息 "data": ......//数据节点 }</code></pre><p><strong>2.终端回复App</strong></p><table><thead><tr><th align="left">0x5A</th><th align="left">数据长度</th><th align="left">框架版本</th><th align="left">协议类型</th><th align="left">设备编码</th><th align="left">Mac地址</th><th align="left">数据帧序列号</th><th align="left">保留字</th><th align="left">数据类型</th><th align="left">数据内容</th><th align="left">检验码FCS</th></tr></thead><tbody><tr><td align="left">5A</td><td align="left">xxxx</td><td align="left">40</td><td align="left">01</td><td align="left">0000000000000000</td><td align="left">000000000000</td><td align="left">00000000</td><td align="left">0000000000000000</td><td align="left">0204</td><td align="left">data</td><td align="left">xxxx</td></tr></tbody></table><ul><li><font color="#c00"> <strong>命令字:0x0204</strong></font> </li><li><font color="#c00"> <strong>data区:json数据</strong></font></li></ul><p>示例:</p><pre><code> { "cmd": 0x00xx ,//命令码 "code": 0,//返回码 "msg": "",//状态消息 "data": ......//数据节点 }</code></pre><h3 id="三、终端主动发送控制数据给App"><a href="#三、终端主动发送控制数据给App" class="headerlink" title="三、终端主动发送控制数据给App"></a><strong>三、终端主动发送控制数据给App</strong></h3><p><strong>1.周期上传运行数据</strong></p><table><thead><tr><th align="left">0x5A</th><th align="left">数据长度</th><th align="left">框架版本</th><th align="left">协议类型</th><th align="left">设备编码</th><th align="left">Mac地址</th><th align="left">数据帧序列号</th><th align="left">保留字</th><th align="left">数据类型</th><th align="left">数据内容</th><th align="left">检验码FCS</th></tr></thead><tbody><tr><td align="left">5A</td><td align="left">xxxx</td><td align="left">40</td><td align="left">01</td><td align="left">0000000000000000</td><td align="left">000000000000</td><td align="left">00000000</td><td align="left">0000000000000000</td><td align="left">0105</td><td align="left">data</td><td align="left">xxxx</td></tr></tbody></table><ul><li><font color="#c00"> <strong>命令字:0x0105</strong></font> </li><li><font color="#c00"> <strong>data区:json数据</strong></font></li></ul><p>示例:</p><pre class="line-numbers language-none"><code class="language-none">{ "cmd": 0x0013 ,//命令码"code": 0,//返回码"msg": "",//状态消息"data": ......//数据节点}</code></pre><hr><h1 id="音箱数据模型"><a href="#音箱数据模型" class="headerlink" title="音箱数据模型"></a><strong>音箱数据模型</strong></h1><h2 id="一、歌单"><a href="#一、歌单" class="headerlink" title="一、歌单"></a><strong>一、歌单</strong></h2><p><strong>参数说明</strong></p><table><thead><tr><th align="left">参数名称</th><th align="left">是否必须</th><th align="left">字段类型</th><th align="left">参数说明</th></tr></thead><tbody><tr><td align="left">id</td><td align="left">是</td><td align="left">int</td><td align="left">歌曲ID</td></tr><tr><td align="left">name</td><td align="left">否</td><td align="left">string</td><td align="left">演唱者</td></tr><tr><td align="left">artist</td><td align="left">否</td><td align="left">String</td><td align="left">艺术家</td></tr><tr><td align="left">album_title</td><td align="left">否</td><td align="left">String</td><td align="left">专辑标题</td></tr><tr><td align="left">lrc_id</td><td align="left">否</td><td align="left">String</td><td align="left">歌词ID</td></tr><tr><td align="left">image_url_small</td><td align="left">否</td><td align="left">String</td><td align="left">歌曲海报1</td></tr><tr><td align="left">image_url_middle</td><td align="left">否</td><td align="left">String</td><td align="left">歌曲海报2</td></tr><tr><td align="left">image_url_large</td><td align="left">否</td><td align="left">String</td><td align="left">歌曲海报3</td></tr><tr><td align="left">mac</td><td align="left">否</td><td align="left">String</td><td align="left">Mac地址</td></tr><tr><td align="left">total_time</td><td align="left">否</td><td align="left">int</td><td align="left">歌曲时长</td></tr><tr><td align="left">album_id</td><td align="left">否</td><td align="left">int</td><td align="left">专辑ID</td></tr><tr><td align="left">utype</td><td align="left">否</td><td align="left">int</td><td align="left">比如 虾米音乐 考虑 喜马拉雅 之类的</td></tr><tr><td align="left">uri</td><td align="left">是</td><td align="left">int</td><td align="left">歌曲URL</td></tr><tr><td align="left">downloadurl</td><td align="left">是</td><td align="left">String</td><td align="left">下载url</td></tr></tbody></table><h2 id="二、播放状态"><a href="#二、播放状态" class="headerlink" title="二、播放状态"></a><strong>二、播放状态</strong></h2><p><strong>参数说明</strong></p><table><thead><tr><th align="left">参数名称</th><th align="left">是否必须</th><th align="left">字段类型</th><th align="left">参数说明</th></tr></thead><tbody><tr><td align="left">id是</td><td align="left">int</td><td align="left">歌曲ID</td><td align="left"></td></tr><tr><td align="left">mtype</td><td align="left">是</td><td align="left">String</td><td align="left">虾米,百度云盘,本地音乐…</td></tr><tr><td align="left">p_status</td><td align="left">否</td><td align="left">int</td><td align="left">“0/1/2/3/4”, //准备播放,播放,暂停,停止,播放结束(用于网络收音机)</td></tr><tr><td align="left">type</td><td align="left">否</td><td align="left">String</td><td align="left">当前播放源(预设preset),收藏,实时推送</td></tr><tr><td align="left">name</td><td align="left">否</td><td align="left">string</td><td align="left">演唱者</td></tr><tr><td align="left">artist</td><td align="left">否</td><td align="left">String</td><td align="left">艺术家</td></tr><tr><td align="left">album</td><td align="left">否</td><td align="left">String</td><td align="left">专辑</td></tr><tr><td align="left">next_id</td><td align="left">是</td><td align="left">int</td><td align="left">下一首歌曲id</td></tr><tr><td align="left">total_time</td><td align="left">是</td><td align="left">int</td><td align="left">歌曲总时间</td></tr><tr><td align="left">current_time</td><td align="left">是</td><td align="left">int</td><td align="left">歌曲当前播放时间</td></tr><tr><td align="left">play_mode</td><td align="left">否</td><td align="left">int</td><td align="left">模式(//顺序播放/随机播放列表循环/单曲循环/)</td></tr><tr><td align="left">volume</td><td align="left">是</td><td align="left">int</td><td align="left">音量</td></tr></tbody></table><h1 id="绑定流程"><a href="#绑定流程" class="headerlink" title="绑定流程"></a><strong>绑定流程</strong></h1><hr><h2 id="title-喜马拉雅WiFi音响绑定及通讯协议初稿date-2016-05-11-22-54-48tags-智能家居-喜马拉雅-Andorid-categories-IoT"><a href="#title-喜马拉雅WiFi音响绑定及通讯协议初稿date-2016-05-11-22-54-48tags-智能家居-喜马拉雅-Andorid-categories-IoT" class="headerlink" title="title: 喜马拉雅WiFi音响绑定及通讯协议初稿date: 2016-05-11 22:54:48tags: [智能家居,喜马拉雅,Andorid]categories:- [IoT]"></a>title: 喜马拉雅WiFi音响绑定及通讯协议初稿<br>date: 2016-05-11 22:54:48<br>tags: [智能家居,喜马拉雅,Andorid]<br>categories:<br>- [IoT]</h2><p>喜马拉雅WiFi音响绑定及通讯协议初稿</p><!--more--><h1 id="通讯协议-1"><a href="#通讯协议-1" class="headerlink" title="通讯协议"></a><strong>通讯协议</strong></h1><p>|0x5A|数据长度|框架版本|协议类型|设备编码|Mac地址|数据帧序列号|保留字|数据类型|数据内容|检验码FCS|<br>|—-|:—-:|<br>|1字节|2字节|1字节|1字节|8字节|6字节|4字节|8字节|2字节|N字节|2字节|</p><h1 id="通讯Json格式:-1"><a href="#通讯Json格式:-1" class="headerlink" title="通讯Json格式:"></a><strong>通讯Json格式</strong>:</h1><pre><code>{ "cmd": 0 ,//命令码"code": 0,//返回码"msg": "",//状态消息"data": ......//数据节点}</code></pre><h2 id="参数说明-1"><a href="#参数说明-1" class="headerlink" title="参数说明"></a><strong>参数说明</strong></h2><table><thead><tr><th align="left">参数名称</th><th align="left">是否必须</th><th align="left">字段类型</th><th align="left">参数说明</th></tr></thead><tbody><tr><td align="left">cmd</td><td align="left">YES</td><td align="left">int</td><td align="left">命令码</td></tr><tr><td align="left">code</td><td align="left">NO</td><td align="left">int</td><td align="left">返回码</td></tr><tr><td align="left">msg</td><td align="left">NO</td><td align="left">String</td><td align="left">状态消息</td></tr><tr><td align="left">data</td><td align="left">NO</td><td align="left">String</td><td align="left">数据节点</td></tr></tbody></table><h2 id="全局命令码-1"><a href="#全局命令码-1" class="headerlink" title="全局命令码"></a><strong>全局命令码</strong></h2><blockquote><span class="custom-blockquote-svg"><svg width="24" height="24" viewBox="0 0 24 24" fill="" xmlns="http://www.w3.org/2000/svg" data-reactroot=""><path fill="" d="M22 12C22 6.5 17.5 2 12 2C6.5 2 2 6.5 2 12C2 17.5 6.5 22 12 22C13.8 22 15.5 21.5 17 20.6L22 22L20.7 17C21.5 15.5 22 13.8 22 12Z" undefined="1"></path><path fill="" d="M15.97 11.5H16.04C17.12 11.5 18 12.38 18 13.47V13.53C18 14.62 17.12 15.5 16.03 15.5H15.96C14.88 15.5 14 14.62 14 13.53V13.46C14 12.38 14.88 11.5 15.97 11.5Z" undefined="1"></path><path fill="" d="M7.97 11.5H8.04C9.12 11.5 10 12.38 10 13.47V13.53C10 14.62 9.12 15.5 8.03 15.5H7.97C6.88 15.5 6 14.62 6 13.53V13.46C6 12.38 6.88 11.5 7.97 11.5Z" undefined="1"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M17 8.5C15.23 8.97 14.07 10.84 14.01 13.27C14 13.33 14 13.4 14 13.47V13.5"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M9 8.5C7.23 8.97 6.07 10.84 6.01 13.27C6 13.33 6 13.4 6 13.47V13.5"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M15.97 11.5H16.04C17.12 11.5 18 12.38 18 13.47V13.53C18 14.62 17.12 15.5 16.03 15.5H15.96C14.88 15.5 14 14.62 14 13.53V13.46C14 12.38 14.88 11.5 15.97 11.5Z"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M7.97 11.5H8.04C9.12 11.5 10 12.38 10 13.47V13.53C10 14.62 9.12 15.5 8.03 15.5H7.97C6.88 15.5 6 14.62 6 13.53V13.46C6 12.38 6.88 11.5 7.97 11.5Z"></path></svg></span><p>每一种操作对用一个命令码,用作标识指令。</p></blockquote><h4 id="全局命令码说明如下:-1"><a href="#全局命令码说明如下:-1" class="headerlink" title="全局命令码说明如下:"></a>全局命令码说明如下:</h4><table><thead><tr><th align="left">命令码(十六进制)</th><th align="left">十进制</th><th align="left">说明</th></tr></thead><tbody><tr><td align="left">0x0001</td><td align="left">1</td><td align="left">添加歌曲</td></tr><tr><td align="left">0x0002</td><td align="left">2</td><td align="left">App查询歌曲列表</td></tr><tr><td align="left">0x0003</td><td align="left">3</td><td align="left">升级操作</td></tr><tr><td align="left">0x0004</td><td align="left">4</td><td align="left">播放</td></tr><tr><td align="left">0x0005</td><td align="left">5</td><td align="left">关机</td></tr><tr><td align="left">0x0006</td><td align="left">6</td><td align="left">静音/解除静音</td></tr><tr><td align="left">0x0007</td><td align="left">7</td><td align="left">音量+</td></tr><tr><td align="left">0x0008</td><td align="left">8</td><td align="left">音量-</td></tr><tr><td align="left">0x0009</td><td align="left">9</td><td align="left">切换aux状态</td></tr><tr><td align="left">0x000a</td><td align="left">10</td><td align="left">下一曲</td></tr><tr><td align="left">0x000b</td><td align="left">11</td><td align="left">上一曲</td></tr><tr><td align="left">0x000c</td><td align="left">12</td><td align="left">暂停</td></tr><tr><td align="left">0x000d</td><td align="left">13</td><td align="left">App查询播放状态</td></tr><tr><td align="left">0x000e</td><td align="left">14</td><td align="left">WIFI 无线简易连接</td></tr><tr><td align="left">0x000f</td><td align="left">15</td><td align="left">设备回复心跳</td></tr><tr><td align="left">0x400f</td><td align="left">16399</td><td align="left">App发送心跳</td></tr><tr><td align="left">0x0011</td><td align="left">17</td><td align="left">palyMode(顺序播放/随机播放/列表循环/单曲循环/)</td></tr><tr><td align="left">0x0012</td><td align="left">18</td><td align="left">音量设置(直接设置音量值)</td></tr><tr><td align="left">0x0013</td><td align="left">19</td><td align="left">设备推送播放状态</td></tr><tr><td align="left">0x0014</td><td align="left">20</td><td align="left">设备推送播放列表</td></tr><tr><td align="left">0x0015</td><td align="left">21</td><td align="left">拖拽进度条</td></tr></tbody></table><h2 id="全局返回码-1"><a href="#全局返回码-1" class="headerlink" title="全局返回码"></a><strong>全局返回码</strong></h2><blockquote><span class="custom-blockquote-svg"><svg width="24" height="24" viewBox="0 0 24 24" fill="" xmlns="http://www.w3.org/2000/svg" data-reactroot=""><path fill="" d="M22 12C22 6.5 17.5 2 12 2C6.5 2 2 6.5 2 12C2 17.5 6.5 22 12 22C13.8 22 15.5 21.5 17 20.6L22 22L20.7 17C21.5 15.5 22 13.8 22 12Z" undefined="1"></path><path fill="" d="M15.97 11.5H16.04C17.12 11.5 18 12.38 18 13.47V13.53C18 14.62 17.12 15.5 16.03 15.5H15.96C14.88 15.5 14 14.62 14 13.53V13.46C14 12.38 14.88 11.5 15.97 11.5Z" undefined="1"></path><path fill="" d="M7.97 11.5H8.04C9.12 11.5 10 12.38 10 13.47V13.53C10 14.62 9.12 15.5 8.03 15.5H7.97C6.88 15.5 6 14.62 6 13.53V13.46C6 12.38 6.88 11.5 7.97 11.5Z" undefined="1"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M17 8.5C15.23 8.97 14.07 10.84 14.01 13.27C14 13.33 14 13.4 14 13.47V13.5"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M9 8.5C7.23 8.97 6.07 10.84 6.01 13.27C6 13.33 6 13.4 6 13.47V13.5"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M15.97 11.5H16.04C17.12 11.5 18 12.38 18 13.47V13.53C18 14.62 17.12 15.5 16.03 15.5H15.96C14.88 15.5 14 14.62 14 13.53V13.46C14 12.38 14.88 11.5 15.97 11.5Z"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M7.97 11.5H8.04C9.12 11.5 10 12.38 10 13.47V13.53C10 14.62 9.12 15.5 8.03 15.5H7.97C6.88 15.5 6 14.62 6 13.53V13.46C6 12.38 6.88 11.5 7.97 11.5Z"></path></svg></span><p>每次调用接口时,可能获得正确或错误的返回码,可以根据返回码信息调试接口,排查错误。<br>####全局返回码说明如下:</p><table><thead><tr><th align="left">0</th><th align="left">请求成功</th></tr></thead><tbody><tr><td align="left">200</td><td align="left">无错误</td></tr><tr><td align="left">400</td><td align="left">不支持此接口</td></tr><tr><td align="left">401</td><td align="left">JSON数据解析错误</td></tr></tbody></table></blockquote><h2 id="示例-1"><a href="#示例-1" class="headerlink" title="示例"></a><strong>示例</strong></h2><h3 id="字符串-1"><a href="#字符串-1" class="headerlink" title="字符串"></a><strong>字符串</strong></h3><pre><code>{ "cmd": 0x0001 ,//命令码"code": 0, //返回码"msg": "", //状态消息"data": "This is string" //数据节点}</code></pre><h3 id="整形参数-1"><a href="#整形参数-1" class="headerlink" title="整形参数"></a><strong>整形参数</strong></h3><pre><code>{ "cmd": 0x0001 ,//命令码"code": 0, //返回码"msg": "", //状态消息"data": 1 //数据节点}</code></pre><h3 id="对象-1"><a href="#对象-1" class="headerlink" title="对象"></a><strong>对象</strong></h3><pre><code>{ "cmd": 0x0001 ,//命令码"code": 0, //返回码"msg": "", //状态消息"data": { "ssid":"TP-link", //连接的路由名称 "password":"12345678", //路由密码,需要加密 } }</code></pre><h3 id="数组-1"><a href="#数组-1" class="headerlink" title="数组"></a><strong>数组</strong></h3><pre><code>{ "cmd": 0x001 ,//命令码"code": 0, //返回码"msg": "", //状态消息"data":[ { "id" : "0" "name" : “xxxx", "artist" : “xxxx", "album_title": “xxxx", "cover_url_small”:“xxxx", "cover_url_middle":"xxxx", "cover_url_large":"xxxx", "url":"xxxxxxxxx" {详细规格见规格说明url部分}, }, { "id":"1" "name":"xxxx1", "artist":"xxxx1", "album":"xxxx1", "cover_url_small":"xxxx", "cover_url_middle":"xxxx", "cover_url_large":"xxxx", "url":"xxxxxxxxxx"{详细规格见规格说明url部分}, } ]}</code></pre><h2 id="指令说明-1"><a href="#指令说明-1" class="headerlink" title="指令说明"></a><strong>指令说明</strong></h2><h3 id="一、设备基础指令-1"><a href="#一、设备基础指令-1" class="headerlink" title="一、设备基础指令"></a><strong>一、设备基础指令</strong></h3><ol><li><strong>App扫描设备</strong></li></ol><table><thead><tr><th align="left">0x5A</th><th align="left">数据长度</th><th align="left">框架版本</th><th align="left">协议类型</th><th align="left">设备编码</th><th align="left">Mac地址</th><th align="left">数据帧序列号</th><th align="left">保留字</th><th align="left">数据类型</th><th align="left">数据内容</th><th align="left">检验码FCS</th></tr></thead><tbody><tr><td align="left">5A</td><td align="left">0022</td><td align="left">40</td><td align="left">01</td><td align="left">0000000000000000</td><td align="left">000000000000</td><td align="left">20000000</td><td align="left">0000000000000000</td><td align="left">0405</td><td align="left">data</td><td align="left">381a</td></tr></tbody></table><ul><li><font color="#c00"><strong>命令字:0x0405</strong></font></li><li><font color="#c00"><strong>data区:NULL</strong></font></li></ul><ol start="2"><li><strong>设备回复自身信息</strong></li></ol><table><thead><tr><th align="left">0x5A</th><th align="left">数据长度</th><th align="left">框架版本</th><th align="left">协议类型</th><th align="left">设备编码</th><th align="left">Mac地址</th><th align="left">数据帧序列号</th><th align="left">保留字</th><th align="left">数据类型</th><th align="left">数据内容</th><th align="left">检验码FCS</th></tr></thead><tbody><tr><td align="left">5A</td><td align="left">xxxx</td><td align="left">40</td><td align="left">01</td><td align="left">00000199001b0300</td><td align="left">d8f710e019b0</td><td align="left">00000000</td><td align="left">0000000000000000</td><td align="left">0305</td><td align="left">data</td><td align="left">xxxx</td></tr></tbody></table><ul><li><font color="#c00"><strong>命令字:0x0305</strong></font></li><li><font color="#c00"><strong>厂商ID:0x0199</strong> </font></li><li><font color="#c00"><strong>大分类:0x1b</strong> </font></li><li><font color="#c00"><strong>小分类:0x03</strong></font></li></ul><ol start="3"><li><strong>App发送心跳包</strong><table><thead><tr><th align="left">0x5A</th><th align="left">数据长度</th><th align="left">框架版本</th><th align="left">协议类型</th><th align="left">设备编码</th><th align="left">Mac地址</th><th align="left">数据帧序列号</th><th align="left">保留字</th><th align="left">数据类型</th><th align="left">数据内容</th><th align="left">检验码FCS</th></tr></thead><tbody><tr><td align="left">5A</td><td align="left">xxxx</td><td align="left">40</td><td align="left">01</td><td align="left">0000000000000000</td><td align="left">000000000000</td><td align="left">20000000</td><td align="left">0000000000000000</td><td align="left">0104</td><td align="left">data</td><td align="left">xxxx</td></tr></tbody></table></li></ol><ul><li><font color="#c00"><strong>命令字:0x0104</strong></font></li><li><font color="#c00"><strong>data区:json</strong></font></li></ul><p>示例:</p><pre><code> { "cmd": 0x400f ,//命令码 "code": 0,//返回码 "msg": "",//状态消息 "data": ......//数据节点 }</code></pre><ol start="4"><li><strong>设备回复心跳</strong></li></ol><table><thead><tr><th align="left">0x5A</th><th align="left">数据长度</th><th align="left">框架版本</th><th align="left">协议类型</th><th align="left">设备编码</th><th align="left">Mac地址</th><th align="left">数据帧序列号</th><th align="left">保留字</th><th align="left">数据类型</th><th align="left">数据内容</th><th align="left">检验码FCS</th></tr></thead><tbody><tr><td align="left">5A</td><td align="left">xxxx</td><td align="left">40</td><td align="left">01</td><td align="left">0000000000000000</td><td align="left">000000000000</td><td align="left">00000000</td><td align="left">0000000000000000</td><td align="left">0204</td><td align="left">data</td><td align="left">xxxx</td></tr></tbody></table><ul><li><font color="#c00"> <strong>命令字:0x0204</strong></font> </li><li><font color="#c00"> <strong>data区:json</strong></font></li></ul><p>示例:</p><pre><code> { "cmd": 0x000f ,//命令码 "code": 0,//返回码 "msg": "",//状态消息 "data": { "deviceId": "SPK设备序列号" } }</code></pre><h3 id="二、App主动控制终端指令-1"><a href="#二、App主动控制终端指令-1" class="headerlink" title="二、App主动控制终端指令"></a><strong>二、App主动控制终端指令</strong></h3><p><strong>1.App控制终端</strong></p><table><thead><tr><th align="left">0x5A</th><th align="left">数据长度</th><th align="left">框架版本</th><th align="left">协议类型</th><th align="left">设备编码</th><th align="left">Mac地址</th><th align="left">数据帧序列号</th><th align="left">保留字</th><th align="left">数据类型</th><th align="left">数据内容</th><th align="left">检验码FCS</th></tr></thead><tbody><tr><td align="left">5A</td><td align="left">xxxx</td><td align="left">40</td><td align="left">01</td><td align="left">0000000000000000</td><td align="left">000000000000</td><td align="left">00000000</td><td align="left">0000000000000000</td><td align="left">0104</td><td align="left">data</td><td align="left">xxxx</td></tr></tbody></table><ul><li><font color="#c00"> <strong>命令字:0x0104</strong></font> </li><li><font color="#c00"> <strong>data区:json数据</strong></font></li></ul><p>示例:</p><pre><code> { "cmd": 0x00xx ,//命令码 "code": 0,//返回码 "msg": "",//状态消息 "data": ......//数据节点 }</code></pre><p><strong>2.终端回复App</strong></p><table><thead><tr><th align="left">0x5A</th><th align="left">数据长度</th><th align="left">框架版本</th><th align="left">协议类型</th><th align="left">设备编码</th><th align="left">Mac地址</th><th align="left">数据帧序列号</th><th align="left">保留字</th><th align="left">数据类型</th><th align="left">数据内容</th><th align="left">检验码FCS</th></tr></thead><tbody><tr><td align="left">5A</td><td align="left">xxxx</td><td align="left">40</td><td align="left">01</td><td align="left">0000000000000000</td><td align="left">000000000000</td><td align="left">00000000</td><td align="left">0000000000000000</td><td align="left">0204</td><td align="left">data</td><td align="left">xxxx</td></tr></tbody></table><ul><li><font color="#c00"> <strong>命令字:0x0204</strong></font> </li><li><font color="#c00"> <strong>data区:json数据</strong></font></li></ul><p>示例:</p><pre><code> { "cmd": 0x00xx ,//命令码 "code": 0,//返回码 "msg": "",//状态消息 "data": ......//数据节点 }</code></pre><h3 id="三、终端主动发送控制数据给App-1"><a href="#三、终端主动发送控制数据给App-1" class="headerlink" title="三、终端主动发送控制数据给App"></a><strong>三、终端主动发送控制数据给App</strong></h3><p><strong>1.周期上传运行数据</strong></p><table><thead><tr><th align="left">0x5A</th><th align="left">数据长度</th><th align="left">框架版本</th><th align="left">协议类型</th><th align="left">设备编码</th><th align="left">Mac地址</th><th align="left">数据帧序列号</th><th align="left">保留字</th><th align="left">数据类型</th><th align="left">数据内容</th><th align="left">检验码FCS</th></tr></thead><tbody><tr><td align="left">5A</td><td align="left">xxxx</td><td align="left">40</td><td align="left">01</td><td align="left">0000000000000000</td><td align="left">000000000000</td><td align="left">00000000</td><td align="left">0000000000000000</td><td align="left">0105</td><td align="left">data</td><td align="left">xxxx</td></tr></tbody></table><ul><li><font color="#c00"> <strong>命令字:0x0105</strong></font> </li><li><font color="#c00"> <strong>data区:json数据</strong></font></li></ul><p>示例:</p><pre class="line-numbers language-none"><code class="language-none">{ "cmd": 0x0013 ,//命令码"code": 0,//返回码"msg": "",//状态消息"data": ......//数据节点}</code></pre><hr><h1 id="音箱数据模型-1"><a href="#音箱数据模型-1" class="headerlink" title="音箱数据模型"></a><strong>音箱数据模型</strong></h1><h2 id="一、歌单-1"><a href="#一、歌单-1" class="headerlink" title="一、歌单"></a><strong>一、歌单</strong></h2><p><strong>参数说明</strong></p><table><thead><tr><th align="left">参数名称</th><th align="left">是否必须</th><th align="left">字段类型</th><th align="left">参数说明</th></tr></thead><tbody><tr><td align="left">id</td><td align="left">是</td><td align="left">int</td><td align="left">歌曲ID</td></tr><tr><td align="left">name</td><td align="left">否</td><td align="left">string</td><td align="left">演唱者</td></tr><tr><td align="left">artist</td><td align="left">否</td><td align="left">String</td><td align="left">艺术家</td></tr><tr><td align="left">album_title</td><td align="left">否</td><td align="left">String</td><td align="left">专辑标题</td></tr><tr><td align="left">lrc_id</td><td align="left">否</td><td align="left">String</td><td align="left">歌词ID</td></tr><tr><td align="left">image_url_small</td><td align="left">否</td><td align="left">String</td><td align="left">歌曲海报1</td></tr><tr><td align="left">image_url_middle</td><td align="left">否</td><td align="left">String</td><td align="left">歌曲海报2</td></tr><tr><td align="left">image_url_large</td><td align="left">否</td><td align="left">String</td><td align="left">歌曲海报3</td></tr><tr><td align="left">mac</td><td align="left">否</td><td align="left">String</td><td align="left">Mac地址</td></tr><tr><td align="left">total_time</td><td align="left">否</td><td align="left">int</td><td align="left">歌曲时长</td></tr><tr><td align="left">album_id</td><td align="left">否</td><td align="left">int</td><td align="left">专辑ID</td></tr><tr><td align="left">utype</td><td align="left">否</td><td align="left">int</td><td align="left">比如 虾米音乐 考虑 喜马拉雅 之类的</td></tr><tr><td align="left">uri</td><td align="left">是</td><td align="left">int</td><td align="left">歌曲URL</td></tr><tr><td align="left">downloadurl</td><td align="left">是</td><td align="left">String</td><td align="left">下载url</td></tr></tbody></table><h2 id="二、播放状态-1"><a href="#二、播放状态-1" class="headerlink" title="二、播放状态"></a><strong>二、播放状态</strong></h2><p><strong>参数说明</strong></p><table><thead><tr><th align="left">参数名称</th><th align="left">是否必须</th><th align="left">字段类型</th><th align="left">参数说明</th></tr></thead><tbody><tr><td align="left">id是</td><td align="left">int</td><td align="left">歌曲ID</td><td align="left"></td></tr><tr><td align="left">mtype</td><td align="left">是</td><td align="left">String</td><td align="left">虾米,百度云盘,本地音乐…</td></tr><tr><td align="left">p_status</td><td align="left">否</td><td align="left">int</td><td align="left">“0/1/2/3/4”, //准备播放,播放,暂停,停止,播放结束(用于网络收音机)</td></tr><tr><td align="left">type</td><td align="left">否</td><td align="left">String</td><td align="left">当前播放源(预设preset),收藏,实时推送</td></tr><tr><td align="left">name</td><td align="left">否</td><td align="left">string</td><td align="left">演唱者</td></tr><tr><td align="left">artist</td><td align="left">否</td><td align="left">String</td><td align="left">艺术家</td></tr><tr><td align="left">album</td><td align="left">否</td><td align="left">String</td><td align="left">专辑</td></tr><tr><td align="left">next_id</td><td align="left">是</td><td align="left">int</td><td align="left">下一首歌曲id</td></tr><tr><td align="left">total_time</td><td align="left">是</td><td align="left">int</td><td align="left">歌曲总时间</td></tr><tr><td align="left">current_time</td><td align="left">是</td><td align="left">int</td><td align="left">歌曲当前播放时间</td></tr><tr><td align="left">play_mode</td><td align="left">否</td><td align="left">int</td><td align="left">模式(//顺序播放/随机播放列表循环/单曲循环/)</td></tr><tr><td align="left">volume</td><td align="left">是</td><td align="left">int</td><td align="left">音量</td></tr></tbody></table><h1 id="绑定流程-1"><a href="#绑定流程-1" class="headerlink" title="绑定流程"></a><strong>绑定流程</strong></h1><img src="/post/ximalaya/bind.jpg" class="" title="这里写图片描述"><p><em><strong><a href="ximalaya/bind.jpg">点击看大图</a></strong></em></p><p><a href="http://blog.csdn.net/xxl6097/article/details/50127949"><strong>[原文链接地址]http://blog.csdn.net/xxl6097/article/details/50127949</strong></a></p><p><a href="http://blog.csdn.net/xxl6097/article/details/50127949"><strong>[原文链接地址]http://blog.csdn.net/xxl6097/article/details/50127949</strong></a></p>]]></content>
<categories>
<category> IoT </category>
</categories>
<tags>
<tag> Andorid </tag>
<tag> 智能家居 </tag>
<tag> 喜马拉雅 </tag>
</tags>
</entry>
<entry>
<title>绑定界面动资源画动态替换</title>
<link href="//post/public-bind.html"/>
<url>//post/public-bind.html</url>
<content type="html"><![CDATA[<p>由于公共模块绑定满足不了TOB项目以及其他项目特殊需求,现对公共模块绑定界面的资源做成可配置,本文介绍一下哪些资源可配置以及如何配置。</p><span id="more"></span><h3 id="颜色配置"><a href="#颜色配置" class="headerlink" title="颜色配置"></a>颜色配置</h3><p> 颜色的配置需要在<strong>res/values,res/values-v14,res/values-v19,res/values-v21</strong>等目录下新建<br> <font color="red" face="黑体" size="4">color.xml</font>。<br> color.xml内容如下:</p><pre class="line-numbers language-none"><code class="language-none"><?xml version="1.0" encoding="utf-8"?><resources> <color name="title_bar_bg_color">#FFFF4444</color></resources></code></pre><p> 目录结构如图1所示</p><img src="/post/public-bind/values.png" class="" title="img1"><p><strong>图1</strong></p><p><strong>1.标题颜</strong></p><pre class="line-numbers language-none"><code class="language-none"><?xml version="1.0" encoding="utf-8"?><resources> <color name="title_bar_bg_color">填入需要配置的颜色值(#FFFF0000)</color></resources></code></pre><p><strong>2.子分类列表背景色</strong></p><pre class="line-numbers language-none"><code class="language-none"><?xml version="1.0" encoding="utf-8"?><resources> <color name="color_app_themes">填入需要配置的颜色值(#FFFF0000)</color></resources></code></pre><h3 id="绑定动画配置"><a href="#绑定动画配置" class="headerlink" title="绑定动画配置"></a>绑定动画配置</h3><blockquote><span class="custom-blockquote-svg"><svg width="24" height="24" viewBox="0 0 24 24" fill="" xmlns="http://www.w3.org/2000/svg" data-reactroot=""><path fill="" d="M22 12C22 6.5 17.5 2 12 2C6.5 2 2 6.5 2 12C2 17.5 6.5 22 12 22C13.8 22 15.5 21.5 17 20.6L22 22L20.7 17C21.5 15.5 22 13.8 22 12Z" undefined="1"></path><path fill="" d="M15.97 11.5H16.04C17.12 11.5 18 12.38 18 13.47V13.53C18 14.62 17.12 15.5 16.03 15.5H15.96C14.88 15.5 14 14.62 14 13.53V13.46C14 12.38 14.88 11.5 15.97 11.5Z" undefined="1"></path><path fill="" d="M7.97 11.5H8.04C9.12 11.5 10 12.38 10 13.47V13.53C10 14.62 9.12 15.5 8.03 15.5H7.97C6.88 15.5 6 14.62 6 13.53V13.46C6 12.38 6.88 11.5 7.97 11.5Z" undefined="1"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M17 8.5C15.23 8.97 14.07 10.84 14.01 13.27C14 13.33 14 13.4 14 13.47V13.5"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M9 8.5C7.23 8.97 6.07 10.84 6.01 13.27C6 13.33 6 13.4 6 13.47V13.5"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M15.97 11.5H16.04C17.12 11.5 18 12.38 18 13.47V13.53C18 14.62 17.12 15.5 16.03 15.5H15.96C14.88 15.5 14 14.62 14 13.53V13.46C14 12.38 14.88 11.5 15.97 11.5Z"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M7.97 11.5H8.04C9.12 11.5 10 12.38 10 13.47V13.53C10 14.62 9.12 15.5 8.03 15.5H7.97C6.88 15.5 6 14.62 6 13.53V13.46C6 12.38 6.88 11.5 7.97 11.5Z"></path></svg></span><p>在主工程<strong>res/drawable</strong>下分别新建<strong>bind_scanning_anim.xml、bind_bouding_anim.xml、bind_failed_anim.xml、bind_sucess_anim.xml</strong>资源文件;</p></blockquote><p>1.<strong>“扫描中“动画</strong>(bind_scanning_anim.xml),代码如下:</p><pre class="line-numbers language-none"><code class="language-none"><?xml version="1.0" encoding="utf-8"?><!-- 根标签为animation-list,其中oneshot代表着是否只展示一遍,设置为false会不停的循环播放动画 根标签下,通过item标签对动画中的每一个图片进行声明 android:duration 表示展示所用的该图片的时间长度 --><animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="false"> <item android:drawable="@drawable/scan1" android:duration="150"></item> <item android:drawable="@drawable/scan2" android:duration="150"></item></animation-list></code></pre><ul><li>扫描中 使用帧动画,默认配置中两帧,即:scan1.png和scan2.png</li><li>图片分辨率:201x307</li></ul><p>2.<strong>绑定中 动画</strong>(bind_bouding_anim.xml),代码如下:</p><pre class="line-numbers language-none"><code class="language-none"><?xml version="1.0" encoding="utf-8"?><!-- 根标签为animation-list,其中oneshot代表着是否只展示一遍,设置为false会不停的循环播放动画 根标签下,通过item标签对动画中的每一个图片进行声明 android:duration 表示展示所用的该图片的时间长度 --><animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="false"> <item android:drawable="@drawable/bouding1" android:duration="150"></item> <item android:drawable="@drawable/bouding2" android:duration="150"></item> <item android:drawable="@drawable/bouding3" android:duration="150"></item> <item android:drawable="@drawable/bouding4" android:duration="150"></item> <item android:drawable="@drawable/bouding5" android:duration="150"></item></animation-list></code></pre><ul><li>绑定中 使用帧动画,默认配置使用5帧,即:bouding1.png、bouding2.png、bouding3.png、bouding4.png、bouding5.png</li><li>图片分辨率:392x276</li></ul><p>3.<strong>失败 动画</strong>(bind_failed_anim.xml),代码如下:</p><pre class="line-numbers language-none"><code class="language-none"><?xml version="1.0" encoding="utf-8"?><!-- 根标签为animation-list,其中oneshot代表着是否只展示一遍,设置为false会不停的循环播放动画 根标签下,通过item标签对动画中的每一个图片进行声明 android:duration 表示展示所用的该图片的时间长度 --><animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="false"> <item android:drawable="@drawable/failed1" android:duration="150"></item> <item android:drawable="@drawable/failed2" android:duration="150"></item></animation-list></code></pre><ul><li>扫描中 使用帧动画,默认配置使用2帧,即:failed1.png和failed2.png</li><li>图片分辨率:203x306</li></ul><p>4.<strong>成功 动画</strong>(bind_sucess_anim.xml),代码如下:</p><pre class="line-numbers language-none"><code class="language-none"><?xml version="1.0" encoding="utf-8"?><!-- 根标签为animation-list,其中oneshot代表着是否只展示一遍,设置为false会不停的循环播放动画 根标签下,通过item标签对动画中的每一个图片进行声明 android:duration 表示展示所用的该图片的时间长度 --><animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="false"> <item android:drawable="@drawable/sucess1" android:duration="150"></item> <item android:drawable="@drawable/sucess2" android:duration="150"></item></animation-list></code></pre><ul><li>扫描中 使用帧动画,默认配置使用2帧,即:sucess1.png和sucess2.png</li><li>图片分辨率:203x306</li></ul><h3 id="网络请求loadding图标配置"><a href="#网络请求loadding图标配置" class="headerlink" title="网络请求loadding图标配置"></a>网络请求loadding图标配置</h3><p>在主工程<strong>res/drawable</strong>下分别新建<strong>bind_network_waiting.xml</strong>资源文件。<br>代码如下:</p><pre class="line-numbers language-none"><code class="language-none"><?xml version="1.0" encoding="utf-8"?><animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="false"> <item android:drawable="@drawable/load1" android:duration="200" /> <item android:drawable="@drawable/load2" android:duration="200" /></animation-list></code></pre><ul><li>网络请求loadding 使用帧动画,默认配置使用2帧,即:load1.png和load2.png</li><li>图片分辨率:126x126</li></ul><p>缺省配置如图2:</p><img src="/post/public-bind/loading.png" class="" title="img1"><p><strong>图2</strong></p><h3 id="下拉列表Header动画配置"><a href="#下拉列表Header动画配置" class="headerlink" title="下拉列表Header动画配置"></a>下拉列表Header动画配置</h3><p>在主工程<strong>res/drawable</strong>下分别新建<strong>bind_droplistview_anim.xml</strong>资源文件。<br>代码如下:</p><pre class="line-numbers language-none"><code class="language-none"><?xml version="1.0" encoding="utf-8"?><!-- 根标签为animation-list,其中oneshot代表着是否只展示一遍,设置为false会不停的循环播放动画 根标签下,通过item标签对动画中的每一个图片进行声明 android:duration 表示展示所用的该图片的时间长度 --><animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="false"> <item android:drawable="@drawable/list1" android:duration="150"></item> <item android:drawable="@drawable/list2" android:duration="150"></item> <item android:drawable="@drawable/list3" android:duration="150"></item> <item android:drawable="@drawable/list4" android:duration="150"></item> <item android:drawable="@drawable/list5" android:duration="150"></item></animation-list></code></pre><ul><li>下拉列表Header动画 使用帧动画,默认配置使用5帧,即:list1.png、list2.png、list3.png、list4.png、list5.png</li><li>图片分辨率:72x72</li></ul><p>缺省配置如图3:</p><img src="/post/public-bind/droplist.png" class="" title="img1"><p><strong>图3</strong></p>]]></content>
<categories>
<category> IoT </category>
</categories>
<tags>
<tag> het </tag>
<tag> 智能家居 </tag>
</tags>
</entry>
<entry>
<title>CentOS下shadowsocks-libev一键安装脚本</title>
<link href="//post/installshadowsocks.html"/>
<url>//post/installshadowsocks.html</url>
<content type="html"><![CDATA[<p>一键安装 libev 版的 shadowsocks 最新版本。该版本的特点是内存占用小(600k左右),低 CPU 消耗,甚至可以安装在基于 OpenWRT 的路由器上。<br>友情提示:如果你有问题,请先参考这篇《<a href="https://teddysun.com/399.html">Shadowsocks Troubleshooting</a>》后再问。</p><span id="more"></span><h2 id="系统要求"><a href="#系统要求" class="headerlink" title="系统要求"></a>系统要求</h2><p>系统支持:CentOS 32或64位<br>内存要求:≥128M<br>日期:2015年08月01日</p><h2 id="本脚本适用环境:"><a href="#本脚本适用环境:" class="headerlink" title="本脚本适用环境:"></a>本脚本适用环境:</h2><p>系统支持:CentOS 32或64位<br>内存要求:≥128M<br>日期:2015年08月01日</p><h2 id="关于本脚本:"><a href="#关于本脚本:" class="headerlink" title="关于本脚本:"></a>关于本脚本:</h2><p>一键安装 libev 版的 shadowsocks 最新版本。该版本的特点是内存占用小(600k左右),低 CPU 消耗,甚至可以安装在基于 OpenWRT 的路由器上。<br>友情提示:如果你有问题,请先参考这篇《<a href="https://teddysun.com/399.html">Shadowsocks Troubleshooting</a>》后再问。</p><h2 id="默认配置:"><a href="#默认配置:" class="headerlink" title="默认配置:"></a>默认配置:</h2><p>服务器端口:自己设定(如不设定,默认为 8989)<br>客户端端口:1080<br>密码:自己设定(如不设定,默认为teddysun.com)</p><h2 id="客户端下载:"><a href="#客户端下载:" class="headerlink" title="客户端下载:"></a>客户端下载:</h2><p><a href="http://sourceforge.net/projects/shadowsocksgui/files/dist/">http://sourceforge.net/projects/shadowsocksgui/files/dist/</a></p><h2 id="使用方法:"><a href="#使用方法:" class="headerlink" title="使用方法:"></a>使用方法:</h2><p>使用root用户登录,运行以下命令:</p><ol><li>获取安装文件</li></ol><pre class="line-numbers language-bash" data-language="bash"><code class="language-bash">wget --no-check-certificate https://raw.githubusercontent.com/teddysun/shadowsocks_install/master/shadowsocks-libev.sh</code></pre><ol start="2"><li>设置执行权限</li></ol><pre class="line-numbers language-bash" data-language="bash"><code class="language-bash">chmod +x shadowsocks-libev.sh</code></pre><ol start="3"><li>按照命令</li></ol><pre class="line-numbers language-bash" data-language="bash"><code class="language-bash">./shadowsocks-libev.sh 2>&1 | tee shadowsocks-libev.log</code></pre><p><em><strong>安装完成后,脚本提示如下:</strong></em></p><pre class="line-numbers language-bash" data-language="bash"><code class="language-bash">Congratulations, shadowsocks-libev install completed!Your Server IP:your_server_ipYour Server Port:your_server_portYour Password:your_passwordYour Local IP:127.0.0.1Your Local Port:1080Your Encryption Method:aes-256-cfbWelcome to visit:https://teddysun.com/357.htmlEnjoy it!</code></pre><ol start="4"><li>安装完成后即已后台启动 shadowsocks ,运行</li></ol><pre class="line-numbers language-bash" data-language="bash"><code class="language-bash">ps -ef | grep ss-server | grep -v ps | grep -v grep</code></pre><ol start="5"><li>使用命令</li></ol><blockquote><span class="custom-blockquote-svg"><svg width="24" height="24" viewBox="0 0 24 24" fill="" xmlns="http://www.w3.org/2000/svg" data-reactroot=""><path fill="" d="M22 12C22 6.5 17.5 2 12 2C6.5 2 2 6.5 2 12C2 17.5 6.5 22 12 22C13.8 22 15.5 21.5 17 20.6L22 22L20.7 17C21.5 15.5 22 13.8 22 12Z" undefined="1"></path><path fill="" d="M15.97 11.5H16.04C17.12 11.5 18 12.38 18 13.47V13.53C18 14.62 17.12 15.5 16.03 15.5H15.96C14.88 15.5 14 14.62 14 13.53V13.46C14 12.38 14.88 11.5 15.97 11.5Z" undefined="1"></path><path fill="" d="M7.97 11.5H8.04C9.12 11.5 10 12.38 10 13.47V13.53C10 14.62 9.12 15.5 8.03 15.5H7.97C6.88 15.5 6 14.62 6 13.53V13.46C6 12.38 6.88 11.5 7.97 11.5Z" undefined="1"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M17 8.5C15.23 8.97 14.07 10.84 14.01 13.27C14 13.33 14 13.4 14 13.47V13.5"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M9 8.5C7.23 8.97 6.07 10.84 6.01 13.27C6 13.33 6 13.4 6 13.47V13.5"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M15.97 11.5H16.04C17.12 11.5 18 12.38 18 13.47V13.53C18 14.62 17.12 15.5 16.03 15.5H15.96C14.88 15.5 14 14.62 14 13.53V13.46C14 12.38 14.88 11.5 15.97 11.5Z"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M7.97 11.5H8.04C9.12 11.5 10 12.38 10 13.47V13.53C10 14.62 9.12 15.5 8.03 15.5H7.97C6.88 15.5 6 14.62 6 13.53V13.46C6 12.38 6.88 11.5 7.97 11.5Z"></path></svg></span><p>启动:/etc/init.d/shadowsocks start<br>停止:/etc/init.d/shadowsocks stop<br>重启:/etc/init.d/shadowsocks restart<br>查看状态:/etc/init.d/shadowsocks status</p></blockquote><ol start="6"><li>卸载方法</li></ol><pre class="line-numbers language-bash" data-language="bash"><code class="language-bash">./shadowsocks-libev.sh uninstall</code></pre><ol start="7"><li>更多版本 shadowsocks 安装</li></ol><p><a href="https://shadowsocks.be/9.html">ShadowsocksR 版一键安装脚本(CentOS,Debian,Ubuntu)</a><br><a href="https://teddysun.com/342.html">Shadowsocks Python 版一键安装脚本(CentOS,Debian,Ubuntu)</a><br><a href="https://teddysun.com/358.html">Debian 下 Shadowsocks-libev 一键安装脚本</a><br><a href="https://teddysun.com/392.html">Shadowsocks-go 一键安装脚本(CentOS,Debian,Ubuntu)</a></p><p>更新说明(2015 年 08 月 01 日):<br>1、新增自定义服务器端口功能(如不设定,默认为 8989);<br>更新说明(2015 年 04 月 30 日):<br>1、本脚本会始终安装最新版的 Shadowsocks;<br>2、修改配置文件 /etc/shadowsocks-libev/config.json 同时启用 IPv4 与 IPv6 支持:</p><pre class="line-numbers language-bash" data-language="bash"><code class="language-bash">{ "server":["[::0]","0.0.0.0"], "server_port":your_server_port, "local_address":"127.0.0.1", "local_port":1080, "password":"your_password", "timeout":600, "method":"aes-256-cfb"}</code></pre><p>3、Shadowsocks libev 版不能通过修改配置文件来多端口(只能开启多进程),如果你需要多端口请安装 Python 或 Go 版;</p><p>特别说明:<br>1、已安装旧版本的 shadowsocks 需要升级的话,需下载本脚本的最新版,运行卸载命令</p><blockquote><span class="custom-blockquote-svg"><svg width="24" height="24" viewBox="0 0 24 24" fill="" xmlns="http://www.w3.org/2000/svg" data-reactroot=""><path fill="" d="M22 12C22 6.5 17.5 2 12 2C6.5 2 2 6.5 2 12C2 17.5 6.5 22 12 22C13.8 22 15.5 21.5 17 20.6L22 22L20.7 17C21.5 15.5 22 13.8 22 12Z" undefined="1"></path><path fill="" d="M15.97 11.5H16.04C17.12 11.5 18 12.38 18 13.47V13.53C18 14.62 17.12 15.5 16.03 15.5H15.96C14.88 15.5 14 14.62 14 13.53V13.46C14 12.38 14.88 11.5 15.97 11.5Z" undefined="1"></path><path fill="" d="M7.97 11.5H8.04C9.12 11.5 10 12.38 10 13.47V13.53C10 14.62 9.12 15.5 8.03 15.5H7.97C6.88 15.5 6 14.62 6 13.53V13.46C6 12.38 6.88 11.5 7.97 11.5Z" undefined="1"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M17 8.5C15.23 8.97 14.07 10.84 14.01 13.27C14 13.33 14 13.4 14 13.47V13.5"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M9 8.5C7.23 8.97 6.07 10.84 6.01 13.27C6 13.33 6 13.4 6 13.47V13.5"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M15.97 11.5H16.04C17.12 11.5 18 12.38 18 13.47V13.53C18 14.62 17.12 15.5 16.03 15.5H15.96C14.88 15.5 14 14.62 14 13.53V13.46C14 12.38 14.88 11.5 15.97 11.5Z"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M7.97 11.5H8.04C9.12 11.5 10 12.38 10 13.47V13.53C10 14.62 9.12 15.5 8.03 15.5H7.97C6.88 15.5 6 14.62 6 13.53V13.46C6 12.38 6.88 11.5 7.97 11.5Z"></path></svg></span><p>./shadowsocks-libev.sh uninstall<br>然后,再次执行本脚本即可安装最新版。</p></blockquote><p>参考链接:<br><a href="https://github.com/madeye/shadowsocks-libev">https://github.com/madeye/shadowsocks-libev</a></p>]]></content>
<categories>
<category> VPN </category>
<category> shadowsocks </category>
<category> centos6 </category>
</categories>
<tags>
<tag> shadowsocks </tag>
<tag> 科学上网 </tag>
<tag> centos6 </tag>
</tags>
</entry>
<entry>
<title>ios开发笔记</title>
<link href="//post/iosdev.html"/>
<url>//post/iosdev.html</url>
<content type="html"><![CDATA[<p><a href="http://www.williamlong.info/archives/4319.html">http://www.williamlong.info/archives/4319.html</a></p><ul><li><input checked="" disabled="" type="checkbox"> 证书知识及准备工作</li><li><input checked="" disabled="" type="checkbox"> 几种开发者帐号区别</li><li><input checked="" disabled="" type="checkbox"> 真机调试流程</li><li><input checked="" disabled="" type="checkbox"> 内测发布流程</li><li><input disabled="" type="checkbox"> Appstore 上架流程<span id="more"></span></li></ul><h2 id="目录导航"><a href="#目录导航" class="headerlink" title="目录导航"></a>目录导航</h2><ul><li><a href="#%E8%AF%81%E4%B9%A6%E7%9F%A5%E8%AF%86%E5%8F%8A%E5%87%86%E5%A4%87%E5%B7%A5%E4%BD%9C">证书知识及准备工作</a><ul><li><a href="#%E5%9F%BA%E7%A1%80%E9%97%AE%E9%A2%98%E7%AD%94%E7%96%91">基础问题答疑</a><ul><li><a href="#%E4%BB%80%E4%B9%88%E6%98%AF%E8%AF%81%E4%B9%A6">什么是证书</a></li><li><a href="#%E4%BB%80%E4%B9%88%E6%97%B6%E5%80%99%E9%9C%80%E8%A6%81%E8%AF%81%E4%B9%A6">什么时候需要证书</a></li><li><a href="#%E8%AF%81%E4%B9%A6%E5%A6%82%E4%BD%95%E8%8E%B7%E5%BE%97">证书如何获得</a></li><li><a href="#%E5%A6%82%E4%BD%95%E5%AF%B9%E4%BB%A3%E7%A0%81%E8%BF%9B%E8%A1%8C%E7%AD%BE%E5%90%8D">如何对代码进行签名</a></li><li><a href="#%E6%88%91%E7%94%9F%E6%88%90%E7%9A%84%E7%A7%81%E9%92%A5%E5%A6%82%E4%BD%95%E5%85%B1%E4%BA%AB%E7%BB%99%E5%9B%A2%E9%98%9F%E6%88%90%E5%91%98">我生成的私钥如何共享给团队成员</a></li></ul></li><li><a href="#%E5%90%84%E6%B5%81%E7%A8%8B%E4%B8%AD%E8%AF%81%E4%B9%A6%E7%9A%84%E9%9C%80%E6%B1%82%E6%83%85%E5%86%B5">各流程中证书的需求情况</a><ul><li><a href="#%E6%A8%A1%E6%8B%9F%E5%99%A8%E8%B0%83%E8%AF%95">模拟器调试</a></li><li><a href="#%E7%9C%9F%E6%9C%BA%E8%B0%83%E8%AF%95">真机调试</a></li><li><a href="#%E6%89%93%E5%8C%85%E5%92%8C%E5%8F%91%E5%B8%83">打包和发布</a></li><li><a href="#%E6%B6%88%E6%81%AF%E6%8E%A8%E9%80%81%E5%90%8E%E7%AB%AF%E6%9C%8D%E5%8A%A1">消息推送后端服务</a></li></ul></li><li><a href="#%E5%BC%80%E5%8F%91%E4%B8%AD%E5%B8%B8%E8%A7%81%E7%9A%84%E8%AF%81%E4%B9%A6%E5%8F%8A%E7%9B%B8%E5%85%B3%E6%96%87%E4%BB%B6%E4%BB%8B%E7%BB%8D">开发中常见的证书及相关文件介绍</a><ul><li><a href="#csrcertificate-request-%E6%96%87%E4%BB%B6">CSR(certificate request) 文件</a></li><li><a href="#%E5%BC%80%E5%8F%91%E8%80%85%E8%AF%81%E4%B9%A6">开发者证书</a></li><li><a href="#apnsapple-push-notification-service-%E8%AF%81%E4%B9%A6">apns(Apple Push Notification Service) 证书</a></li><li><a href="#p12personal-information-exchange-%E8%AF%81%E4%B9%A6">p12(Personal Information Exchange) 证书</a></li><li><a href="##%E6%8F%8F%E8%BF%B0%E6%96%87%E4%BB%B6provisioning-profiles">描述文件(Provisioning Profiles)</a></li></ul></li><li><a href="#%E9%99%84%E5%BD%951-%E5%BC%80%E5%8F%91%E5%87%86%E5%A4%87%E7%9B%B8%E5%85%B3%E7%9A%84%E7%BD%91%E5%9D%80">附录1: 开发准备相关的网址</a></li></ul></li><li><a href="#%E5%87%A0%E7%A7%8D%E5%BC%80%E5%8F%91%E8%80%85%E5%B8%90%E5%8F%B7%E5%8C%BA%E5%88%AB">几种开发者帐号区别</a><ul><li><a href="#%E5%85%B3%E9%94%AE%E5%8C%BA%E5%88%AB">关键区别</a></li></ul></li><li><a href="#%E7%9C%9F%E6%9C%BA%E8%B0%83%E8%AF%95%E6%B5%81%E7%A8%8B">真机调试流程</a><ul><li><a href="##%E5%9F%BA%E6%9C%AC%E6%A6%82%E5%BF%B5">基本概念</a></li><li><a href="#%E6%9D%A1%E4%BB%B6%E5%92%8C%E6%B5%81%E7%A8%8B">条件和流程</a></li></ul></li><li><a href="#%E5%86%85%E6%B5%8B%E5%8F%91%E5%B8%83%E6%B5%81%E7%A8%8B">内测发布流程</a><ul><li><a href="#%E5%9F%BA%E6%9C%AC%E6%A6%82%E5%BF%B5-1">基本概念</a></li><li><a href="#%E5%AE%9E%E7%8E%B0%E6%9D%A1%E4%BB%B6">实现条件</a></li><li><a href="#%E5%87%A0%E7%A7%8D%E5%B8%B8%E8%A7%81%E7%9A%84%E5%88%86%E5%8F%91%E9%80%94%E5%BE%84">几种常见的分发途径</a></li><li><a href="#%E9%99%84%E5%BD%952-%E5%B8%B8%E8%A7%81%E5%88%86%E5%8F%91%E6%B8%A0%E9%81%93%E5%8F%8A%E5%B7%A5%E5%85%B7%E5%9C%B0%E5%9D%80">附录2: 常见分发渠道及工具地址</a></li></ul></li><li><a href="#appstore-%E4%B8%8A%E6%9E%B6%E6%B5%81%E7%A8%8B">Appstore 上架流程</a><ul><li><a href="#%E9%99%84%E5%BD%953-app-store%E6%9C%80%E6%96%B0%E5%AE%A1%E6%A0%B8%E6%A0%87%E5%87%8620153">附录3: App store最新审核标准(2015.3)</a></li></ul></li></ul><h2 id="证书知识及准备工作"><a href="#证书知识及准备工作" class="headerlink" title="证书知识及准备工作"></a>证书知识及准备工作</h2><h3 id="基础问题答疑"><a href="#基础问题答疑" class="headerlink" title="基础问题答疑"></a>基础问题答疑</h3><h4 id="什么是证书"><a href="#什么是证书" class="headerlink" title="什么是证书"></a>什么是证书</h4><p>由 apple 官方颁发, 用以证明开发者身份的特殊文件, 在 iOS 开发中主要用于代码签名, 保障 iOS 生态的健康安全, 分为开发者证书和发布者证书</p><h4 id="什么时候需要证书"><a href="#什么时候需要证书" class="headerlink" title="什么时候需要证书"></a>什么时候需要证书</h4><p>只有在本机模拟器调试时无需代码签名, 当 App 需要在真机运行和发布时需要使用相应证书进行签名</p><h4 id="证书如何获得"><a href="#证书如何获得" class="headerlink" title="证书如何获得"></a>证书如何获得</h4><p>首先需要拥有相应权限的开发者帐号, 通过在本地生成配对的密钥, 向 <a href="https://developer.apple.com/ios/manage/overview/index.action">provisioning portal</a> 提交公钥后换取, 后续证书在使用时会验证本地私钥</p><h4 id="如何对代码进行签名"><a href="#如何对代码进行签名" class="headerlink" title="如何对代码进行签名"></a>如何对代码进行签名</h4><p>在 xcode 中, 使用描述文件(provision profile 包含调试者证书, 授权设备清单, 应用ID), 在 <code>Build Settings</code> 中选择存于 <code>Keychain Access</code> 中的证书文件设置调试和发布任务时的代码签名</p><h4 id="我生成的私钥如何共享给团队成员"><a href="#我生成的私钥如何共享给团队成员" class="headerlink" title="我生成的私钥如何共享给团队成员"></a>我生成的私钥如何共享给团队成员</h4><p>在 <code>Keychain Access</code> 中找到导入的证书, 右击导出为包含私钥的 Personal Information Exchange(.p12)文件(导出时可以创建密码), 团队成员再导入 <code>p12</code> 证书后就完整包含了证书和私钥</p><h3 id="各流程中证书的需求情况"><a href="#各流程中证书的需求情况" class="headerlink" title="各流程中证书的需求情况"></a>各流程中证书的需求情况</h3><h4 id="模拟器调试"><a href="#模拟器调试" class="headerlink" title="模拟器调试"></a>模拟器调试</h4><p>不需要</p><h4 id="真机调试"><a href="#真机调试" class="headerlink" title="真机调试"></a>真机调试</h4><ul><li><p>描述文件(Provisioning Profiles)</p></li><li><p>开发者证书(ios_development.cer)</p></li></ul><h4 id="打包和发布"><a href="#打包和发布" class="headerlink" title="打包和发布"></a>打包和发布</h4><ul><li><p>描述文件(Provisioning Profiles)</p></li><li><p>可用于发布的开发者证书(ios_distribution.cer)</p></li></ul><h4 id="消息推送后端服务"><a href="#消息推送后端服务" class="headerlink" title="消息推送后端服务"></a>消息推送后端服务</h4><ul><li>apns 证书</li></ul><h3 id="开发中常见的证书及相关文件介绍"><a href="#开发中常见的证书及相关文件介绍" class="headerlink" title="开发中常见的证书及相关文件介绍"></a>开发中常见的证书及相关文件介绍</h3><h4 id="CSR-certificate-request-文件"><a href="#CSR-certificate-request-文件" class="headerlink" title="CSR(certificate request) 文件"></a>CSR(certificate request) 文件</h4><p>用于换取证书的公钥文件, 实际是在本地基于 <code>RSA</code> 加密得到配对的密钥, 私钥存于 <code>Keychain Access</code> 用于签名, 公钥作为换取证书的凭证</p><h5 id="生成方法"><a href="#生成方法" class="headerlink" title="生成方法"></a>生成方法</h5><ul><li><p>OSX 系统自带的 <strong>Keychain Access</strong></p><ul><li><p>选择 “Request a Certificate From a Certificate Authority…”</p></li><li><p>输入 email 等信息后保存为 <code>.certSigningRequest</code> 文件</p></li></ul></li><li><p>命令行下使用 <strong>openssl</strong> 生成</p></li></ul><pre class="line-numbers language-bash" data-language="bash"><code class="language-bash">$ openssl genrsa -out private.key 2048$ openssl req -new -sha256 -key private.key -out my.certSigningRequest</code></pre><h4 id="开发者证书"><a href="#开发者证书" class="headerlink" title="开发者证书"></a>开发者证书</h4><p>由 apple 官方颁发, 用来证明开发者资格的证书文件, 分开发(ios_development.cer)和发布(ios_distribution.cer)两种</p><p><code>cer</code> 证书跟开发机(私钥)绑定只能在拥有私钥的机器上使用, 如果要迁移机器需要导出为 <code>p12</code> 文件</p><h5 id="生成方法-1"><a href="#生成方法-1" class="headerlink" title="生成方法"></a>生成方法</h5><p>在 <a href="https://developer.apple.com/devcenter/ios/index.action">开发者中心</a> “certificates” 面板中添加 <code>certificate</code> 并上传刚刚生成的 <code>CSR</code> 文件, 获取 <code>ios_development.cer</code></p><h4 id="apns-Apple-Push-Notification-Service-证书"><a href="#apns-Apple-Push-Notification-Service-证书" class="headerlink" title="apns(Apple Push Notification Service) 证书"></a>apns(Apple Push Notification Service) 证书</h4><p>用于服务端消息推送, 类似 ssl 证书使用, 和 App 端的开发打包没有关系</p><h5 id="生成方法-2"><a href="#生成方法-2" class="headerlink" title="生成方法"></a>生成方法</h5><p>在 <a href="https://developer.apple.com/devcenter/ios/index.action">开发者中心</a> “Identifiers” 面板中添加 <code>App ID</code> 并上传刚刚生成的 <code>CSR</code> 文件, 获取 <code>aps_production.cer</code></p><h4 id="p12-Personal-Information-Exchange-证书"><a href="#p12-Personal-Information-Exchange-证书" class="headerlink" title="p12(Personal Information Exchange) 证书"></a>p12(Personal Information Exchange) 证书</h4><p><code>p12</code> 证书实际是包含了 <code>cer</code> 证书及私钥信息, 可以分发给团队成员</p><h5 id="生成方法-3"><a href="#生成方法-3" class="headerlink" title="生成方法"></a>生成方法</h5><p>在 <strong>Keychain Access</strong> 中找到已经导入的 <code>cer</code> 证书, 点右键导出为 <code>p12</code> 格式</p><h4 id="描述文件-Provisioning-Profiles"><a href="#描述文件-Provisioning-Profiles" class="headerlink" title="描述文件(Provisioning Profiles)"></a>描述文件(Provisioning Profiles)</h4><p>包含 <code>certificate</code> <code>appID</code> <code>devices id</code> 的文件用于在 xcode 调试打包时提供授权的配置信息</p><h5 id="生成方法-4"><a href="#生成方法-4" class="headerlink" title="生成方法"></a>生成方法</h5><ul><li><p>在 <a href="https://developer.apple.com/devcenter/ios/index.action">开发者中心</a> “Provisioning Profiles” 面板中添加 <code>iOS Provisioning Profiles</code> 并上传刚刚生成的 <code>CSR</code> 文件, 获取 <code>.mobileprovision</code> 文件</p></li><li><p>在 xcode 登录开发者帐号后可以连接开发者中心获取</p></li></ul><h3 id="附录1-开发准备相关的网址"><a href="#附录1-开发准备相关的网址" class="headerlink" title="附录1: 开发准备相关的网址"></a>附录1: 开发准备相关的网址</h3><blockquote><span class="custom-blockquote-svg"><svg width="24" height="24" viewBox="0 0 24 24" fill="" xmlns="http://www.w3.org/2000/svg" data-reactroot=""><path fill="" d="M22 12C22 6.5 17.5 2 12 2C6.5 2 2 6.5 2 12C2 17.5 6.5 22 12 22C13.8 22 15.5 21.5 17 20.6L22 22L20.7 17C21.5 15.5 22 13.8 22 12Z" undefined="1"></path><path fill="" d="M15.97 11.5H16.04C17.12 11.5 18 12.38 18 13.47V13.53C18 14.62 17.12 15.5 16.03 15.5H15.96C14.88 15.5 14 14.62 14 13.53V13.46C14 12.38 14.88 11.5 15.97 11.5Z" undefined="1"></path><path fill="" d="M7.97 11.5H8.04C9.12 11.5 10 12.38 10 13.47V13.53C10 14.62 9.12 15.5 8.03 15.5H7.97C6.88 15.5 6 14.62 6 13.53V13.46C6 12.38 6.88 11.5 7.97 11.5Z" undefined="1"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M17 8.5C15.23 8.97 14.07 10.84 14.01 13.27C14 13.33 14 13.4 14 13.47V13.5"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M9 8.5C7.23 8.97 6.07 10.84 6.01 13.27C6 13.33 6 13.4 6 13.47V13.5"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M15.97 11.5H16.04C17.12 11.5 18 12.38 18 13.47V13.53C18 14.62 17.12 15.5 16.03 15.5H15.96C14.88 15.5 14 14.62 14 13.53V13.46C14 12.38 14.88 11.5 15.97 11.5Z"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M7.97 11.5H8.04C9.12 11.5 10 12.38 10 13.47V13.53C10 14.62 9.12 15.5 8.03 15.5H7.97C6.88 15.5 6 14.62 6 13.53V13.46C6 12.38 6.88 11.5 7.97 11.5Z"></path></svg></span><p>开发者中心<br><a href="https://developer.apple.com/devcenter/ios/index.action">https://developer.apple.com/devcenter/ios/index.action</a></p><p>iOS 描述管理(配置证书、描述文件、推送服务)<br><a href="https://developer.apple.com/ios/manage/overview/index.action">https://developer.apple.com/ios/manage/overview/index.action</a></p><p>切换团队(在 web 界面上死活没有找到)<br><a href="https://developer.apple.com/account/selectTeam.action">https://developer.apple.com/account/selectTeam.action</a></p><p>iOS 上架 Appstore<br><a href="http://itunesconnect.apple.com/">http://itunesconnect.apple.com/</a></p></blockquote><h2 id="几种开发者帐号区别"><a href="#几种开发者帐号区别" class="headerlink" title="几种开发者帐号区别"></a>几种开发者帐号区别</h2><blockquote><span class="custom-blockquote-svg"><svg width="24" height="24" viewBox="0 0 24 24" fill="" xmlns="http://www.w3.org/2000/svg" data-reactroot=""><path fill="" d="M22 12C22 6.5 17.5 2 12 2C6.5 2 2 6.5 2 12C2 17.5 6.5 22 12 22C13.8 22 15.5 21.5 17 20.6L22 22L20.7 17C21.5 15.5 22 13.8 22 12Z" undefined="1"></path><path fill="" d="M15.97 11.5H16.04C17.12 11.5 18 12.38 18 13.47V13.53C18 14.62 17.12 15.5 16.03 15.5H15.96C14.88 15.5 14 14.62 14 13.53V13.46C14 12.38 14.88 11.5 15.97 11.5Z" undefined="1"></path><path fill="" d="M7.97 11.5H8.04C9.12 11.5 10 12.38 10 13.47V13.53C10 14.62 9.12 15.5 8.03 15.5H7.97C6.88 15.5 6 14.62 6 13.53V13.46C6 12.38 6.88 11.5 7.97 11.5Z" undefined="1"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M17 8.5C15.23 8.97 14.07 10.84 14.01 13.27C14 13.33 14 13.4 14 13.47V13.5"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M9 8.5C7.23 8.97 6.07 10.84 6.01 13.27C6 13.33 6 13.4 6 13.47V13.5"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M15.97 11.5H16.04C17.12 11.5 18 12.38 18 13.47V13.53C18 14.62 17.12 15.5 16.03 15.5H15.96C14.88 15.5 14 14.62 14 13.53V13.46C14 12.38 14.88 11.5 15.97 11.5Z"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M7.97 11.5H8.04C9.12 11.5 10 12.38 10 13.47V13.53C10 14.62 9.12 15.5 8.03 15.5H7.97C6.88 15.5 6 14.62 6 13.53V13.46C6 12.38 6.88 11.5 7.97 11.5Z"></path></svg></span><p>详见: <a href="https://developer.apple.com/programs/start/ios/">https://developer.apple.com/programs/start/ios/</a></p></blockquote><ul><li><a href="https://developer.apple.com/programs/ios/">个人(individual)</a> <strong>$99</strong>/year</li><li><a href="https://developer.apple.com/programs/ios/">公司(company)</a> <strong>$99</strong>/year</li><li><a href="https://developer.apple.com/programs/ios/enterprise/">企业(enterprise)</a> <strong>$299</strong>/year</li><li><a href="https://developer.apple.com/programs/start/university/">大学(University)</a> <strong>free</strong></li></ul><h3 id="关键区别"><a href="#关键区别" class="headerlink" title="关键区别"></a>关键区别</h3><ul><li>个人帐号可以真机调试, 发布 appstore, 每年 最多为 100台设备分发</li><li>公司帐号和个人帐号类似, 只有这两种帐号可以发布 appstore, 主要特权是可以添加多个开发者子账号, 但只允许主账号提交, 发布等操作, 在协同开发时比较灵活, 可以各自管理授权设备等</li><li>企业帐号<strong>无法用于 appstore 发布</strong>, 但可以不通过 appstore 发布任意 iphone 都可以安装的应用</li><li>大学帐号不能发布 appstore, 主要拥有真机调试的权限</li></ul><h2 id="真机调试流程"><a href="#真机调试流程" class="headerlink" title="真机调试流程"></a>真机调试流程</h2><h3 id="基本概念"><a href="#基本概念" class="headerlink" title="基本概念"></a>基本概念</h3><p>真机调试指 mac 连上 iphone, xcode 可以直接以这台 iphone 设备为 build target, 能在 iphone 里执行编译结果</p><h3 id="条件和流程"><a href="#条件和流程" class="headerlink" title="条件和流程"></a>条件和流程</h3><p>分为拥有独立开发者帐号(也包括公司帐号或企业帐号成员)和共享开发者帐号两种情况</p><h4 id="拥有独立开发者帐号"><a href="#拥有独立开发者帐号" class="headerlink" title="拥有独立开发者帐号"></a>拥有独立开发者帐号</h4><ul><li><ol><li>在 <a href="https://developer.apple.com/ios/manage/overview/index.action">provisioning portal</a> 新建应用, 配置授权设备等</li></ol></li><li><ol start="2"><li>开发机上导入证书</li></ol></li><li><ol start="3"><li>在 xcode 上登录开发者帐号, 不需要准备描述文件, xcode 会自动生成(如果是公司帐号可以自动生成 <code>iOS Team Provisioning Profile</code>)</li></ol></li></ul><h4 id="共享开发者帐号"><a href="#共享开发者帐号" class="headerlink" title="共享开发者帐号"></a>共享开发者帐号</h4><p>如果无法在 xcode 登录一个开发者帐号, 也可以通过他人对你手机和应用 id 的授权, 得到 <code>.mobileprovision</code> 描述文件再导入其含私钥的证书(<code>p12</code>) 即可, 具体步骤如下:</p><ul><li><ol><li>获得手机的 <code>udid</code> (可以连上 mac, 在 itunes 中查看)</li></ol></li><li><ol start="2"><li>告知对方 <code>udid</code> (用以设备授权) 和 应用 id</li></ol></li><li><ol start="3"><li>得到对方生成的证书和描述文件后, 先导入 <code>p12</code> 证书, 再双击 <code>mobileprovision</code> 文件</li></ol></li><li><ol start="4"><li>连接手机, 在 xcode 中选择 build target 为已连接的手机</li></ol></li></ul><blockquote><span class="custom-blockquote-svg"><svg width="24" height="24" viewBox="0 0 24 24" fill="" xmlns="http://www.w3.org/2000/svg" data-reactroot=""><path fill="" d="M22 12C22 6.5 17.5 2 12 2C6.5 2 2 6.5 2 12C2 17.5 6.5 22 12 22C13.8 22 15.5 21.5 17 20.6L22 22L20.7 17C21.5 15.5 22 13.8 22 12Z" undefined="1"></path><path fill="" d="M15.97 11.5H16.04C17.12 11.5 18 12.38 18 13.47V13.53C18 14.62 17.12 15.5 16.03 15.5H15.96C14.88 15.5 14 14.62 14 13.53V13.46C14 12.38 14.88 11.5 15.97 11.5Z" undefined="1"></path><path fill="" d="M7.97 11.5H8.04C9.12 11.5 10 12.38 10 13.47V13.53C10 14.62 9.12 15.5 8.03 15.5H7.97C6.88 15.5 6 14.62 6 13.53V13.46C6 12.38 6.88 11.5 7.97 11.5Z" undefined="1"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M17 8.5C15.23 8.97 14.07 10.84 14.01 13.27C14 13.33 14 13.4 14 13.47V13.5"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M9 8.5C7.23 8.97 6.07 10.84 6.01 13.27C6 13.33 6 13.4 6 13.47V13.5"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M15.97 11.5H16.04C17.12 11.5 18 12.38 18 13.47V13.53C18 14.62 17.12 15.5 16.03 15.5H15.96C14.88 15.5 14 14.62 14 13.53V13.46C14 12.38 14.88 11.5 15.97 11.5Z"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M7.97 11.5H8.04C9.12 11.5 10 12.38 10 13.47V13.53C10 14.62 9.12 15.5 8.03 15.5H7.97C6.88 15.5 6 14.62 6 13.53V13.46C6 12.38 6.88 11.5 7.97 11.5Z"></path></svg></span><p>对刚入门的个人开发者而言, 可以在淘宝搜 <code>iOS真机调试</code> 花几元购买一份授权, 包含(<code>p12</code> 证书 和 <code>.mobileprovision</code> 描述文件)</p></blockquote><h2 id="内测发布流程"><a href="#内测发布流程" class="headerlink" title="内测发布流程"></a>内测发布流程</h2><h3 id="基本概念-1"><a href="#基本概念-1" class="headerlink" title="基本概念"></a>基本概念</h3><p>当 App 开发进行到一定程度, 需要更多的人参与测试, 需要谋求一种方式方便应用能安装进更多的设备中</p><h3 id="实现条件"><a href="#实现条件" class="headerlink" title="实现条件"></a>实现条件</h3><p>进行内测发布主要的关键点是:</p><ul><li><ol><li>是如何将应用打包为 <code>.ipa</code></li></ol></li></ul><p>xcode6 以后, 个人/公司帐号无法对应用打包为 <code>.ipa</code>, 要么用 xcode5 打包要么拥有企业帐号级别的授权</p><ul><li><ol start="2"><li>设备需不需要授权</li></ol></li></ul><p>个人/公司帐号权限只有在 <code>TestFlight</code> / 越狱渠道下完成不授权安装; 企业帐号授权可以在 <code>ad-hoc</code> / <code>in-house</code> 渠道下分发, 完成不授权设备安装</p><h3 id="几种常见的分发途径"><a href="#几种常见的分发途径" class="headerlink" title="几种常见的分发途径"></a>几种常见的分发途径</h3><ul><li>ad-hoc</li></ul><p>打包时必须在登录企业帐号(或其成员)并已导入证书和描述文件的情况下, 任何用户(未授权)都可以在手机上用浏览器访问一个 url(例: itms-services://?action=download-manifest&url=<a href="https://example.com/manifest.plist">https://example.com/manifest.plist</a>) 完成安装</p><p>最大的问题是安装量有 100 的上限, 无法作为一个量很大的分发渠道</p><ul><li>in-house</li></ul><p>针对企业内部用户进行分发, 相比 <code>ad-hoc</code> 无安装量上限</p><blockquote><span class="custom-blockquote-svg"><svg width="24" height="24" viewBox="0 0 24 24" fill="" xmlns="http://www.w3.org/2000/svg" data-reactroot=""><path fill="" d="M22 12C22 6.5 17.5 2 12 2C6.5 2 2 6.5 2 12C2 17.5 6.5 22 12 22C13.8 22 15.5 21.5 17 20.6L22 22L20.7 17C21.5 15.5 22 13.8 22 12Z" undefined="1"></path><path fill="" d="M15.97 11.5H16.04C17.12 11.5 18 12.38 18 13.47V13.53C18 14.62 17.12 15.5 16.03 15.5H15.96C14.88 15.5 14 14.62 14 13.53V13.46C14 12.38 14.88 11.5 15.97 11.5Z" undefined="1"></path><path fill="" d="M7.97 11.5H8.04C9.12 11.5 10 12.38 10 13.47V13.53C10 14.62 9.12 15.5 8.03 15.5H7.97C6.88 15.5 6 14.62 6 13.53V13.46C6 12.38 6.88 11.5 7.97 11.5Z" undefined="1"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M17 8.5C15.23 8.97 14.07 10.84 14.01 13.27C14 13.33 14 13.4 14 13.47V13.5"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M9 8.5C7.23 8.97 6.07 10.84 6.01 13.27C6 13.33 6 13.4 6 13.47V13.5"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M15.97 11.5H16.04C17.12 11.5 18 12.38 18 13.47V13.53C18 14.62 17.12 15.5 16.03 15.5H15.96C14.88 15.5 14 14.62 14 13.53V13.46C14 12.38 14.88 11.5 15.97 11.5Z"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M7.97 11.5H8.04C9.12 11.5 10 12.38 10 13.47V13.53C10 14.62 9.12 15.5 8.03 15.5H7.97C6.88 15.5 6 14.62 6 13.53V13.46C6 12.38 6.88 11.5 7.97 11.5Z"></path></svg></span><p>iOS 8.1.3 开始不能企业证书 Iresign 方式重新签名的应用无法安装<br><a href="https://support.apple.com/en-us/HT204245">https://support.apple.com/en-us/HT204245</a></p></blockquote><ul><li>TestFlight</li></ul><p>仅支持 <strong>iOS8.0</strong> 以上, 不需要对设备 <code>udid</code> 进行授权, 适合个人 / 公司开发者, 在应用发布前可以开启 TestFlight Beta 测试并添加测试者的 iTunes Connect 帐号, 需要待测用户拥有 iTunes Connect 帐号并在设备安装 <code>TestFlight</code> 客户端</p><p>这种方式非常便于推送应用更新和收集测试信息</p><ul><li>导出 ipa 包, 越狱安装</li></ul><p>如果测试设备都越狱了, 这种方式非常灵活简单, 只有能导出 ipa 包就能通过 <a href="http://www.itools.cn/">itools</a> 等第三方工具安装</p><h3 id="附录2-常见分发渠道及工具地址"><a href="#附录2-常见分发渠道及工具地址" class="headerlink" title="附录2: 常见分发渠道及工具地址"></a>附录2: 常见分发渠道及工具地址</h3><blockquote><span class="custom-blockquote-svg"><svg width="24" height="24" viewBox="0 0 24 24" fill="" xmlns="http://www.w3.org/2000/svg" data-reactroot=""><path fill="" d="M22 12C22 6.5 17.5 2 12 2C6.5 2 2 6.5 2 12C2 17.5 6.5 22 12 22C13.8 22 15.5 21.5 17 20.6L22 22L20.7 17C21.5 15.5 22 13.8 22 12Z" undefined="1"></path><path fill="" d="M15.97 11.5H16.04C17.12 11.5 18 12.38 18 13.47V13.53C18 14.62 17.12 15.5 16.03 15.5H15.96C14.88 15.5 14 14.62 14 13.53V13.46C14 12.38 14.88 11.5 15.97 11.5Z" undefined="1"></path><path fill="" d="M7.97 11.5H8.04C9.12 11.5 10 12.38 10 13.47V13.53C10 14.62 9.12 15.5 8.03 15.5H7.97C6.88 15.5 6 14.62 6 13.53V13.46C6 12.38 6.88 11.5 7.97 11.5Z" undefined="1"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M17 8.5C15.23 8.97 14.07 10.84 14.01 13.27C14 13.33 14 13.4 14 13.47V13.5"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M9 8.5C7.23 8.97 6.07 10.84 6.01 13.27C6 13.33 6 13.4 6 13.47V13.5"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M15.97 11.5H16.04C17.12 11.5 18 12.38 18 13.47V13.53C18 14.62 17.12 15.5 16.03 15.5H15.96C14.88 15.5 14 14.62 14 13.53V13.46C14 12.38 14.88 11.5 15.97 11.5Z"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M7.97 11.5H8.04C9.12 11.5 10 12.38 10 13.47V13.53C10 14.62 9.12 15.5 8.03 15.5H7.97C6.88 15.5 6 14.62 6 13.53V13.46C6 12.38 6.88 11.5 7.97 11.5Z"></path></svg></span><p>fir-第三方应用托管平台<br><a href="http://fir.im/">http://fir.im/</a></p><p>TestFlight<br><a href="https://developer.apple.com/testflight/">https://developer.apple.com/testflight/</a></p><p>Agile-百度内部 ios 分发测试平台<br><a href="http://agile.baidu.com/">http://agile.baidu.com</a></p><p>fir-分发相关工具<br><a href="http://fir.im/dev/tools">http://fir.im/dev/tools</a></p><p>itools<br><a href="http://www.itools.cn/">http://www.itools.cn/</a></p></blockquote><h2 id="Appstore-上架流程"><a href="#Appstore-上架流程" class="headerlink" title="Appstore 上架流程"></a>Appstore 上架流程</h2><p>@TODO</p><h3 id="附录3-App-store最新审核标准-2015-3"><a href="#附录3-App-store最新审核标准-2015-3" class="headerlink" title="附录3: App store最新审核标准(2015.3)"></a>附录3: App store最新审核标准(2015.3)</h3><blockquote><span class="custom-blockquote-svg"><svg width="24" height="24" viewBox="0 0 24 24" fill="" xmlns="http://www.w3.org/2000/svg" data-reactroot=""><path fill="" d="M22 12C22 6.5 17.5 2 12 2C6.5 2 2 6.5 2 12C2 17.5 6.5 22 12 22C13.8 22 15.5 21.5 17 20.6L22 22L20.7 17C21.5 15.5 22 13.8 22 12Z" undefined="1"></path><path fill="" d="M15.97 11.5H16.04C17.12 11.5 18 12.38 18 13.47V13.53C18 14.62 17.12 15.5 16.03 15.5H15.96C14.88 15.5 14 14.62 14 13.53V13.46C14 12.38 14.88 11.5 15.97 11.5Z" undefined="1"></path><path fill="" d="M7.97 11.5H8.04C9.12 11.5 10 12.38 10 13.47V13.53C10 14.62 9.12 15.5 8.03 15.5H7.97C6.88 15.5 6 14.62 6 13.53V13.46C6 12.38 6.88 11.5 7.97 11.5Z" undefined="1"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M17 8.5C15.23 8.97 14.07 10.84 14.01 13.27C14 13.33 14 13.4 14 13.47V13.5"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M9 8.5C7.23 8.97 6.07 10.84 6.01 13.27C6 13.33 6 13.4 6 13.47V13.5"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M15.97 11.5H16.04C17.12 11.5 18 12.38 18 13.47V13.53C18 14.62 17.12 15.5 16.03 15.5H15.96C14.88 15.5 14 14.62 14 13.53V13.46C14 12.38 14.88 11.5 15.97 11.5Z"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M7.97 11.5H8.04C9.12 11.5 10 12.38 10 13.47V13.53C10 14.62 9.12 15.5 8.03 15.5H7.97C6.88 15.5 6 14.62 6 13.53V13.46C6 12.38 6.88 11.5 7.97 11.5Z"></path></svg></span><p><a href="Appstore%E6%9C%80%E6%96%B0%E5%AE%A1%E6%A0%B8%E6%A0%87%E5%87%86_2015-3.md">App store最新审核标准(2015.3) 中文翻译</a></p></blockquote><blockquote><span class="custom-blockquote-svg"><svg width="24" height="24" viewBox="0 0 24 24" fill="" xmlns="http://www.w3.org/2000/svg" data-reactroot=""><path fill="" d="M22 12C22 6.5 17.5 2 12 2C6.5 2 2 6.5 2 12C2 17.5 6.5 22 12 22C13.8 22 15.5 21.5 17 20.6L22 22L20.7 17C21.5 15.5 22 13.8 22 12Z" undefined="1"></path><path fill="" d="M15.97 11.5H16.04C17.12 11.5 18 12.38 18 13.47V13.53C18 14.62 17.12 15.5 16.03 15.5H15.96C14.88 15.5 14 14.62 14 13.53V13.46C14 12.38 14.88 11.5 15.97 11.5Z" undefined="1"></path><path fill="" d="M7.97 11.5H8.04C9.12 11.5 10 12.38 10 13.47V13.53C10 14.62 9.12 15.5 8.03 15.5H7.97C6.88 15.5 6 14.62 6 13.53V13.46C6 12.38 6.88 11.5 7.97 11.5Z" undefined="1"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M17 8.5C15.23 8.97 14.07 10.84 14.01 13.27C14 13.33 14 13.4 14 13.47V13.5"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M9 8.5C7.23 8.97 6.07 10.84 6.01 13.27C6 13.33 6 13.4 6 13.47V13.5"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M15.97 11.5H16.04C17.12 11.5 18 12.38 18 13.47V13.53C18 14.62 17.12 15.5 16.03 15.5H15.96C14.88 15.5 14 14.62 14 13.53V13.46C14 12.38 14.88 11.5 15.97 11.5Z"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M7.97 11.5H8.04C9.12 11.5 10 12.38 10 13.47V13.53C10 14.62 9.12 15.5 8.03 15.5H7.97C6.88 15.5 6 14.62 6 13.53V13.46C6 12.38 6.88 11.5 7.97 11.5Z"></path></svg></span><p><a href="https://developer.apple.com/app-store/review/guidelines">App store最新审核标准(2015.3) 英文原版</a></p></blockquote>]]></content>
<categories>
<category> Ios </category>
</categories>
<tags>
<tag> ios </tag>
</tags>
</entry>
<entry>
<title>OkHttp使用教程</title>
<link href="//post/okhttphelp.html"/>
<url>//post/okhttphelp.html</url>
<content type="html"><![CDATA[<p>这是一个针对技术开发者的一个应用,你可以在掘金上获取最新最优质的技术干货,不仅仅是Android知识、前端、后端以至于产品和设计都有涉猎,想成为全栈工程师的朋友不要错过!</p><span id="more"></span><h1 id="入门"><a href="#入门" class="headerlink" title="入门"></a>入门</h1><p>Android系统提供了两种HTTP通信类,HttpURLConnection和HttpClient。<br><a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">关于HttpURLConnection和HttpClient的选择>>官方博客</a><br>尽管Google在大部分安卓版本中推荐使用HttpURLConnection,但是这个类相比HttpClient实在是太难用,太弱爆了。<br>OkHttp是一个相对成熟的解决方案,据说Android4.4的源码中可以看到HttpURLConnection已经替换成OkHttp实现了。所以我们更有理由相信OkHttp的强大。</p><p>OkHttp 处理了很多网络疑难杂症:会从很多常用的连接问题中自动恢复。如果您的服务器配置了多个IP地址,当第一个IP连接失败的时候,OkHttp会自动尝试下一个IP。OkHttp还处理了代理服务器问题和SSL握手失败问题。</p><p>使用 OkHttp 无需重写您程序中的网络代码。OkHttp实现了几乎和java.net.HttpURLConnection一样的API。如果你用了 Apache HttpClient,则OkHttp也提供了一个对应的okhttp-apache 模块。</p><blockquote><span class="custom-blockquote-svg"><svg width="24" height="24" viewBox="0 0 24 24" fill="" xmlns="http://www.w3.org/2000/svg" data-reactroot=""><path fill="" d="M22 12C22 6.5 17.5 2 12 2C6.5 2 2 6.5 2 12C2 17.5 6.5 22 12 22C13.8 22 15.5 21.5 17 20.6L22 22L20.7 17C21.5 15.5 22 13.8 22 12Z" undefined="1"></path><path fill="" d="M15.97 11.5H16.04C17.12 11.5 18 12.38 18 13.47V13.53C18 14.62 17.12 15.5 16.03 15.5H15.96C14.88 15.5 14 14.62 14 13.53V13.46C14 12.38 14.88 11.5 15.97 11.5Z" undefined="1"></path><path fill="" d="M7.97 11.5H8.04C9.12 11.5 10 12.38 10 13.47V13.53C10 14.62 9.12 15.5 8.03 15.5H7.97C6.88 15.5 6 14.62 6 13.53V13.46C6 12.38 6.88 11.5 7.97 11.5Z" undefined="1"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M17 8.5C15.23 8.97 14.07 10.84 14.01 13.27C14 13.33 14 13.4 14 13.47V13.5"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M9 8.5C7.23 8.97 6.07 10.84 6.01 13.27C6 13.33 6 13.4 6 13.47V13.5"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M15.97 11.5H16.04C17.12 11.5 18 12.38 18 13.47V13.53C18 14.62 17.12 15.5 16.03 15.5H15.96C14.88 15.5 14 14.62 14 13.53V13.46C14 12.38 14.88 11.5 15.97 11.5Z"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M7.97 11.5H8.04C9.12 11.5 10 12.38 10 13.47V13.53C10 14.62 9.12 15.5 8.03 15.5H7.97C6.88 15.5 6 14.62 6 13.53V13.46C6 12.38 6.88 11.5 7.97 11.5Z"></path></svg></span><p>注:在国内使用OkHttp会因为这个问题导致部分酷派手机用户无法联网,所以对于大众app来说,需要等待这个bug修复后再使用。或者尝试使用OkHttp的老版本。<br>截止到目前,OkHttp一直没有修复,并把修复计划延迟到了OkHttp2.3中。不是所有设备都能重现,仅少量设备会出现这个问题。(如果问题这么明显,OkHttp早就修复了)</p></blockquote><h2 id="官方资料"><a href="#官方资料" class="headerlink" title="官方资料"></a>官方资料</h2><p><a href="http://square.github.io/okhttp/">官方介绍</a><br><a href="https://github.com/square/okhttp">github源码</a></p><h2 id="使用范围"><a href="#使用范围" class="headerlink" title="使用范围"></a>使用范围</h2><p>OkHttp支持Android 2.3及其以上版本。<br>对于Java, JDK1.7以上。</p><h2 id="jar包准备"><a href="#jar包准备" class="headerlink" title="jar包准备"></a>jar包准备</h2><p>官方介绍页面有链接位置。这里把下载链接也写在下面。<br><a href="http://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy&g=com.squareup.okhttp&a=okhttp&v=LATEST">OkHttp</a><br><a href="http://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy&g=com.squareup.okio&a=okio&v=LATEST">Okio</a></p><h2 id="基本使用"><a href="#基本使用" class="headerlink" title="基本使用"></a>基本使用</h2><p><strong>HTTP GET</strong></p><pre class="line-numbers language-none"><code class="language-none">OkHttpClient client = new OkHttpClient(); String run(String url) throws IOException { Request request = new Request.Builder().url(url).build(); Response response = client.newCall(request).execute(); if (response.isSuccessful()) { return response.body().string(); } else { throw new IOException("Unexpected code " + response); }}</code></pre><p>Request是OkHttp中访问的请求,Builder是辅助类。Response即OkHttp中的响应。<br><strong>Response类:</strong></p><pre class="line-numbers language-none"><code class="language-none">public boolean isSuccessful()Returns true if the code is in [200..300), which means the request was successfully received, understood, and accepted.</code></pre><p><strong>response.body()返回ResponseBody类</strong></p><pre class="line-numbers language-none"><code class="language-none">public final String string() throws IOExceptionReturns the response as a string decoded with the charset of the Content-Type header. If that header is either absent or lacks a charset, this will attempt to decode the response body as UTF-8.Throws:IOException</code></pre><p>当然也能获取到流的形式:</p><pre class="line-numbers language-none"><code class="language-none">public final InputStream byteStream()</code></pre><p><strong>HTTP POST<br>POST提交Json数据</strong></p><pre class="line-numbers language-none"><code class="language-none">public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");OkHttpClient client = new OkHttpClient();String post(String url, String json) throws IOException { RequestBody body = RequestBody.create(JSON, json); Request request = new Request.Builder() .url(url) .post(body) .build(); Response response = client.newCall(request).execute(); f (response.isSuccessful()) { return response.body().string(); } else { throw new IOException("Unexpected code " + response); }}</code></pre><p>使用Request的post方法来提交请求体RequestBody</p><p>** POST提交键值对**<br>很多时候我们会需要通过POST方式把键值对数据传送到服务器。 OkHttp提供了很方便的方式来做这件事情。</p><pre class="line-numbers language-none"><code class="language-none">OkHttpClient client = new OkHttpClient();String post(String url, String json) throws IOException { RequestBody formBody = new FormEncodingBuilder() .add("platform", "android") .add("name", "bug") .add("subject", "XXXXXXXXXXXXXXX") .build(); Request request = new Request.Builder() .url(url) .post(body) .build(); Response response = client.newCall(request).execute(); if (response.isSuccessful()) { return response.body().string(); } else { throw new IOException("Unexpected code " + response); }}</code></pre><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>通过上面的例子我们可以发现,OkHttp在很多时候使用都是很方便的,而且很多代码也有重复,因此特地整理了下面的工具类。<br>注意:</p><ul><li>OkHttp官方文档并不建议我们创建多个OkHttpClient,因此全局使用一个。 如果有需要,可以使用clone方法,再进行自定义。这点在后面的高级教程里会提到。</li><li>enqueue为OkHttp提供的异步方法,入门教程中并没有提到,后面的高级教程里会有解释。</li></ul><pre class="line-numbers language-none"><code class="language-none">import java.io.IOException;import java.util.List;import java.util.concurrent.TimeUnit;import org.apache.http.client.utils.URLEncodedUtils;import org.apache.http.message.BasicNameValuePair;import cn.wiz.sdk.constant.WizConstant;import com.squareup.okhttp.Callback;import com.squareup.okhttp.OkHttpClient;import com.squareup.okhttp.Request;import com.squareup.okhttp.Response; public class OkHttpUtil { private static final OkHttpClient mOkHttpClient = new OkHttpClient(); static{ mOkHttpClient.setConnectTimeout(30, TimeUnit.SECONDS); } /** * 该不会开启异步线程。 * @param request * @return * @throws IOException */ public static Response execute(Request request) throws IOException{ return mOkHttpClient.newCall(request).execute(); } /** * 开启异步线程访问网络 * @param request * @param responseCallback */ public static void enqueue(Request request, Callback responseCallback){ mOkHttpClient.newCall(request).enqueue(responseCallback); } /** * 开启异步线程访问网络, 且不在意返回结果(实现空callback) * @param request */ public static void enqueue(Request request){ mOkHttpClient.newCall(request).enqueue(new Callback() { @Override public void onResponse(Response arg0) throws IOException { } @Override public void onFailure(Request arg0, IOException arg1) { } }); } public static String getStringFromServer(String url) throws IOException{ Request request = new Request.Builder().url(url).build(); Response response = execute(request); if (response.isSuccessful()) { String responseUrl = response.body().string(); return responseUrl; } else { throw new IOException("Unexpected code " + response); } } private static final String CHARSET_NAME = "UTF-8"; /** * 这里使用了HttpClinet的API。只是为了方便 * @param params * @return */ public static String formatParams(List<BasicNameValuePair> params){ return URLEncodedUtils.format(params, CHARSET_NAME); } /** * 为HttpGet 的 url 方便的添加多个name value 参数。 * @param url * @param params * @return */ public static String attachHttpGetParams(String url, List<BasicNameValuePair> params){ return url + "?" + formatParams(params); } /** * 为HttpGet 的 url 方便的添加1个name value 参数。 * @param url * @param name * @param value * @return */ public static String attachHttpGetParam(String url, String name, String value){ return url + "?" + name + "=" + value; }}</code></pre><h2 id="高级"><a href="#高级" class="headerlink" title="高级"></a>高级</h2><p>高级属性其实用的不多,这里主要是对OkHttp github官方教程进行了翻译。</p><h2 id="同步get"><a href="#同步get" class="headerlink" title="同步get"></a>同步get</h2><p>下载一个文件,打印他的响应头,以string形式打印响应体。<br>响应体的 string() 方法对于小文档来说十分方便、高效。但是如果响应体太大(超过1MB),应避免适应 string()方法 ,因为他会将把整个文档加载到内存中。<br>对于超过1MB的响应body,应使用流的方式来处理body。</p><pre class="line-numbers language-none"><code class="language-none">private final OkHttpClient client = new OkHttpClient(); public void run() throws Exception { Request request = new Request.Builder() .url("http://publicobject.com/helloworld.txt") .build(); Response response = client.newCall(request).execute(); if (!response.isSuccessful()) throw new IOException("Unexpected code " + response); Headers responseHeaders = response.headers(); for (int i = 0; i < responseHeaders.size(); i++) { System.out.println(responseHeaders.name(i) + ": " + responseHeaders.value(i)); } System.out.println(response.body().string());}</code></pre><h2 id="异步get"><a href="#异步get" class="headerlink" title="异步get"></a>异步get</h2><p>在一个工作线程中下载文件,当响应可读时回调Callback接口。读取响应时会阻塞当前线程。OkHttp现阶段不提供异步api来接收响应体。</p><pre class="line-numbers language-none"><code class="language-none">private final OkHttpClient client = new OkHttpClient(); public void run() throws Exception { Request request = new Request.Builder() .url("http://publicobject.com/helloworld.txt") .build(); client.newCall(request).enqueue(new Callback() { @Override public void onFailure(Request request, Throwable throwable) { throwable.printStackTrace(); } @Override public void onResponse(Response response) throws IOException { if (!response.isSuccessful()) throw new IOException("Unexpected code " + response); Headers responseHeaders = response.headers(); for (int i = 0; i < responseHeaders.size(); i++) { System.out.println(responseHeaders.name(i) + ": " + responseHeaders.value(i)); } System.out.println(response.body().string()); } });}</code></pre><h2 id="提取响应头"><a href="#提取响应头" class="headerlink" title="提取响应头"></a>提取响应头</h2><p>典型的HTTP头 像是一个 Map<String, String> :每个字段都有一个或没有值。但是一些头允许多个值,像Guava的Multimap。例如:HTTP响应里面提供的Vary响应头,就是多值的。OkHttp的api试图让这些情况都适用。<br>当写请求头的时候,使用header(name, value)可以设置唯一的name、value。如果已经有值,旧的将被移除,然后添加新的。使用addHeader(name, value)可以添加多值(添加,不移除已有的)。<br>当读取响应头时,使用header(name)返回最后出现的name、value。通常情况这也是唯一的name、value。如果没有值,那么header(name)将返回null。如果想读取字段对应的所有值,使用headers(name)会返回一个list。<br>为了获取所有的Header,Headers类支持按index访问。</p><pre class="line-numbers language-none"><code class="language-none">private final OkHttpClient client = new OkHttpClient(); public void run() throws Exception { Request request = new Request.Builder() .url("https://api.github.com/repos/square/okhttp/issues") .header("User-Agent", "OkHttp Headers.java") .addHeader("Accept", "application/json; q=0.5") .addHeader("Accept", "application/vnd.github.v3+json") .build(); Response response = client.newCall(request).execute(); if (!response.isSuccessful()) throw new IOException("Unexpected code " + response); System.out.println("Server: " + response.header("Server")); System.out.println("Date: " + response.header("Date")); System.out.println("Vary: " + response.headers("Vary"));}</code></pre><h2 id="Post方式提交String"><a href="#Post方式提交String" class="headerlink" title="Post方式提交String"></a>Post方式提交String</h2><p>使用HTTP POST提交请求到服务。这个例子提交了一个markdown文档到web服务,以HTML方式渲染markdown。因为整个请求体都在内存中,因此避免使用此api提交大文档(大于1MB)。</p><pre class="line-numbers language-none"><code class="language-none">public static final MediaType MEDIA_TYPE_MARKDOWN = MediaType.parse("text/x-markdown; charset=utf-8"); private final OkHttpClient client = new OkHttpClient(); public void run() throws Exception { String postBody = "" + "Releases\n" + "--------\n" + "\n" + " * _1.0_ May 6, 2013\n" + " * _1.1_ June 15, 2013\n" + " * _1.2_ August 11, 2013\n"; Request request = new Request.Builder() .url("https://api.github.com/markdown/raw") .post(RequestBody.create(MEDIA_TYPE_MARKDOWN, postBody)) .build(); Response response = client.newCall(request).execute(); if (!response.isSuccessful()) throw new IOException("Unexpected code " + response); System.out.println(response.body().string());}</code></pre><h2 id="Post方式提交流"><a href="#Post方式提交流" class="headerlink" title="Post方式提交流"></a>Post方式提交流</h2><p>以流的方式POST提交请求体。请求体的内容由流写入产生。这个例子是流直接写入Okio的BufferedSink。你的程序可能会使用OutputStream,你可以使用BufferedSink.outputStream()来获取。</p><pre class="line-numbers language-none"><code class="language-none">public static final MediaType MEDIA_TYPE_MARKDOWN = MediaType.parse("text/x-markdown; charset=utf-8"); private final OkHttpClient client = new OkHttpClient(); public void run() throws Exception { RequestBody requestBody = new RequestBody() { @Override public MediaType contentType() { return MEDIA_TYPE_MARKDOWN; } @Override public void writeTo(BufferedSink sink) throws IOException { sink.writeUtf8("Numbers\n"); sink.writeUtf8("-------\n"); for (int i = 2; i <= 997; i++) { sink.writeUtf8(String.format(" * %s = %s\n", i, factor(i))); } } private String factor(int n) { for (int i = 2; i < n; i++) { int x = n / i; if (x * i == n) return factor(x) + " × " + i; } return Integer.toString(n); } }; Request request = new Request.Builder() .url("https://api.github.com/markdown/raw") .post(requestBody) .build(); Response response = client.newCall(request).execute(); if (!response.isSuccessful()) throw new IOException("Unexpected code " + response); System.out.println(response.body().string());}</code></pre><h2 id="Post方式提交文件"><a href="#Post方式提交文件" class="headerlink" title="Post方式提交文件"></a>Post方式提交文件</h2><p>以文件作为请求体是十分简单的。</p><pre class="line-numbers language-none"><code class="language-none">public static final MediaType MEDIA_TYPE_MARKDOWN = MediaType.parse("text/x-markdown; charset=utf-8"); private final OkHttpClient client = new OkHttpClient(); public void run() throws Exception { File file = new File("README.md"); Request request = new Request.Builder() .url("https://api.github.com/markdown/raw") .post(RequestBody.create(MEDIA_TYPE_MARKDOWN, file)) .build(); Response response = client.newCall(request).execute(); if (!response.isSuccessful()) throw new IOException("Unexpected code " + response); System.out.println(response.body().string());}</code></pre><h2 id="Post方式提交表单"><a href="#Post方式提交表单" class="headerlink" title="Post方式提交表单"></a>Post方式提交表单</h2><p>使用FormEncodingBuilder来构建和HTML</p><form>标签相同效果的请求体。键值对将使用一种HTML兼容形式的URL编码来进行编码。<p></p><pre class="line-numbers language-none"><code class="language-none">private final OkHttpClient client = new OkHttpClient(); public void run() throws Exception { RequestBody formBody = new FormEncodingBuilder() .add("search", "Jurassic Park") .build(); Request request = new Request.Builder() .url("https://en.wikipedia.org/w/index.php") .post(formBody) .build(); Response response = client.newCall(request).execute(); if (!response.isSuccessful()) throw new IOException("Unexpected code " + response); System.out.println(response.body().string());}</code></pre><h2 id="Post方式提交分块请求"><a href="#Post方式提交分块请求" class="headerlink" title="Post方式提交分块请求"></a>Post方式提交分块请求</h2><p>MultipartBuilder可以构建复杂的请求体,与HTML文件上传形式兼容。多块请求体中每块请求都是一个请求体,可以定义自己的请求头。这些请求头可以用来描述这块请求,例如他的Content-Disposition。如果Content-Length和Content-Type可用的话,他们会被自动添加到请求头中。</p><pre class="line-numbers language-none"><code class="language-none">private static final String IMGUR_CLIENT_ID = "...";private static final MediaType MEDIA_TYPE_PNG = MediaType.parse("image/png"); private final OkHttpClient client = new OkHttpClient(); public void run() throws Exception { // Use the imgur image upload API as documented at https://api.imgur.com/endpoints/image RequestBody requestBody = new MultipartBuilder() .type(MultipartBuilder.FORM) .addPart( Headers.of("Content-Disposition", "form-data; name=\"title\""), RequestBody.create(null, "Square Logo")) .addPart( Headers.of("Content-Disposition", "form-data; name=\"image\""), RequestBody.create(MEDIA_TYPE_PNG, new File("website/static/logo-square.png"))) .build(); Request request = new Request.Builder() .header("Authorization", "Client-ID " + IMGUR_CLIENT_ID) .url("https://api.imgur.com/3/image") .post(requestBody) .build(); Response response = client.newCall(request).execute(); if (!response.isSuccessful()) throw new IOException("Unexpected code " + response); System.out.println(response.body().string());}</code></pre><h2 id="使用Gson来解析JSON响应"><a href="#使用Gson来解析JSON响应" class="headerlink" title="使用Gson来解析JSON响应"></a>使用Gson来解析JSON响应</h2><p>Gson是一个在JSON和Java对象之间转换非常方便的api。这里我们用Gson来解析Github API的JSON响应。<br>注意:ResponseBody.charStream()使用响应头Content-Type指定的字符集来解析响应体。默认是UTF-8。</p><pre class="line-numbers language-none"><code class="language-none">private final OkHttpClient client = new OkHttpClient();private final Gson gson = new Gson(); public void run() throws Exception { Request request = new Request.Builder() .url("https://api.github.com/gists/c2a7c39532239ff261be") .build(); Response response = client.newCall(request).execute(); if (!response.isSuccessful()) throw new IOException("Unexpected code " + response); Gist gist = gson.fromJson(response.body().charStream(), Gist.class); for (Map.Entry<String, GistFile> entry : gist.files.entrySet()) { System.out.println(entry.getKey()); System.out.println(entry.getValue().content); }} static class Gist { Map<String, GistFile> files;} static class GistFile { String content;}</code></pre><h2 id="响应缓存"><a href="#响应缓存" class="headerlink" title="响应缓存"></a>响应缓存</h2><p>为了缓存响应,你需要一个你可以读写的缓存目录,和缓存大小的限制。这个缓存目录应该是私有的,不信任的程序应不能读取缓存内容。<br>一个缓存目录同时拥有多个缓存访问是错误的。大多数程序只需要调用一次new OkHttp(),在第一次调用时配置好缓存,然后其他地方只需要调用这个实例就可以了。否则两个缓存示例互相干扰,破坏响应缓存,而且有可能会导致程序崩溃。<br>响应缓存使用HTTP头作为配置。你可以在请求头中添加Cache-Control: max-stale=3600 ,OkHttp缓存会支持。你的服务通过响应头确定响应缓存多长时间,例如使用Cache-Control: max-age=9600。</p><pre class="line-numbers language-none"><code class="language-none">private final OkHttpClient client; public CacheResponse(File cacheDirectory) throws Exception { int cacheSize = 10 * 1024 * 1024; // 10 MiB Cache cache = new Cache(cacheDirectory, cacheSize); client = new OkHttpClient(); client.setCache(cache);} public void run() throws Exception { Request request = new Request.Builder() .url("http://publicobject.com/helloworld.txt") .build(); Response response1 = client.newCall(request).execute(); if (!response1.isSuccessful()) throw new IOException("Unexpected code " + response1); String response1Body = response1.body().string(); System.out.println("Response 1 response: " + response1); System.out.println("Response 1 cache response: " + response1.cacheResponse()); System.out.println("Response 1 network response: " + response1.networkResponse()); Response response2 = client.newCall(request).execute(); if (!response2.isSuccessful()) throw new IOException("Unexpected code " + response2); String response2Body = response2.body().string(); System.out.println("Response 2 response: " + response2); System.out.println("Response 2 cache response: " + response2.cacheResponse()); System.out.println("Response 2 network response: " + response2.networkResponse()); System.out.println("Response 2 equals Response 1? " + response1Body.equals(response2Body));}</code></pre><h2 id="扩展"><a href="#扩展" class="headerlink" title="扩展"></a>扩展</h2><p>在这一节还提到了下面一句:<br>There are cache headers to force a cached response, force a network response, or force the network response to be validated with a conditional GET.</p><p>我不是很懂cache,平时用到的也不多,所以把Google在Android Developers一段相关的解析放到这里吧。</p><h2 id="Force-a-Network-Response"><a href="#Force-a-Network-Response" class="headerlink" title="Force a Network Response"></a>Force a Network Response</h2><p>In some situations, such as after a user clicks a ‘refresh’ button, it may be necessary to skip the cache, and fetch data directly from the server. To force a full refresh, add the no-cache directive:</p><blockquote><span class="custom-blockquote-svg"><svg width="24" height="24" viewBox="0 0 24 24" fill="" xmlns="http://www.w3.org/2000/svg" data-reactroot=""><path fill="" d="M22 12C22 6.5 17.5 2 12 2C6.5 2 2 6.5 2 12C2 17.5 6.5 22 12 22C13.8 22 15.5 21.5 17 20.6L22 22L20.7 17C21.5 15.5 22 13.8 22 12Z" undefined="1"></path><path fill="" d="M15.97 11.5H16.04C17.12 11.5 18 12.38 18 13.47V13.53C18 14.62 17.12 15.5 16.03 15.5H15.96C14.88 15.5 14 14.62 14 13.53V13.46C14 12.38 14.88 11.5 15.97 11.5Z" undefined="1"></path><path fill="" d="M7.97 11.5H8.04C9.12 11.5 10 12.38 10 13.47V13.53C10 14.62 9.12 15.5 8.03 15.5H7.97C6.88 15.5 6 14.62 6 13.53V13.46C6 12.38 6.88 11.5 7.97 11.5Z" undefined="1"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M17 8.5C15.23 8.97 14.07 10.84 14.01 13.27C14 13.33 14 13.4 14 13.47V13.5"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M9 8.5C7.23 8.97 6.07 10.84 6.01 13.27C6 13.33 6 13.4 6 13.47V13.5"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M15.97 11.5H16.04C17.12 11.5 18 12.38 18 13.47V13.53C18 14.62 17.12 15.5 16.03 15.5H15.96C14.88 15.5 14 14.62 14 13.53V13.46C14 12.38 14.88 11.5 15.97 11.5Z"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M7.97 11.5H8.04C9.12 11.5 10 12.38 10 13.47V13.53C10 14.62 9.12 15.5 8.03 15.5H7.97C6.88 15.5 6 14.62 6 13.53V13.46C6 12.38 6.88 11.5 7.97 11.5Z"></path></svg></span><p>connection.addRequestProperty(“Cache-Control”, “no-cache”);</p></blockquote><p>If it is only necessary to force a cached response to be validated by the server, use the more efficient max-age=0 instead:</p><blockquote><span class="custom-blockquote-svg"><svg width="24" height="24" viewBox="0 0 24 24" fill="" xmlns="http://www.w3.org/2000/svg" data-reactroot=""><path fill="" d="M22 12C22 6.5 17.5 2 12 2C6.5 2 2 6.5 2 12C2 17.5 6.5 22 12 22C13.8 22 15.5 21.5 17 20.6L22 22L20.7 17C21.5 15.5 22 13.8 22 12Z" undefined="1"></path><path fill="" d="M15.97 11.5H16.04C17.12 11.5 18 12.38 18 13.47V13.53C18 14.62 17.12 15.5 16.03 15.5H15.96C14.88 15.5 14 14.62 14 13.53V13.46C14 12.38 14.88 11.5 15.97 11.5Z" undefined="1"></path><path fill="" d="M7.97 11.5H8.04C9.12 11.5 10 12.38 10 13.47V13.53C10 14.62 9.12 15.5 8.03 15.5H7.97C6.88 15.5 6 14.62 6 13.53V13.46C6 12.38 6.88 11.5 7.97 11.5Z" undefined="1"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M17 8.5C15.23 8.97 14.07 10.84 14.01 13.27C14 13.33 14 13.4 14 13.47V13.5"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M9 8.5C7.23 8.97 6.07 10.84 6.01 13.27C6 13.33 6 13.4 6 13.47V13.5"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M15.97 11.5H16.04C17.12 11.5 18 12.38 18 13.47V13.53C18 14.62 17.12 15.5 16.03 15.5H15.96C14.88 15.5 14 14.62 14 13.53V13.46C14 12.38 14.88 11.5 15.97 11.5Z"></path><path stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" stroke="" d="M7.97 11.5H8.04C9.12 11.5 10 12.38 10 13.47V13.53C10 14.62 9.12 15.5 8.03 15.5H7.97C6.88 15.5 6 14.62 6 13.53V13.46C6 12.38 6.88 11.5 7.97 11.5Z"></path></svg></span><p>connection.addRequestProperty(“Cache-Control”, “max-age=0”);</p></blockquote><p>##Force a Cache Response<br>Sometimes you’ll want to show resources if they are available immediately, but not otherwise. This can be used so your application can show something while waiting for the latest data to be downloaded. To restrict a request to locally-cached resources, add the only-if-cached directive:</p><pre class="line-numbers language-none"><code class="language-none">try { connection.addRequestProperty("Cache-Control", "only-if-cached"); InputStream cached = connection.getInputStream(); // the resource was cached! show it catch (FileNotFoundException e) { // the resource was not cached }}</code></pre><p>This technique works even better in situations where a stale response is better than no response. To permit stale cached responses, use the max-stale directive with the maximum staleness in seconds:</p><pre class="line-numbers language-none"><code class="language-none">int maxStale = 60 * 60 * 24 * 28; // tolerate 4-weeks staleconnection.addRequestProperty("Cache-Control", "max-stale=" + maxStale);</code></pre><p>以上信息来自:<a href="http://developer.android.com/reference/android/net/http/HttpResponseCache.html">HttpResponseCache - Android SDK | Android Developers</a></p><h2 id="取消一个Call"><a href="#取消一个Call" class="headerlink" title="取消一个Call"></a>取消一个Call</h2><p>使用Call.cancel()可以立即停止掉一个正在执行的call。如果一个线程正在写请求或者读响应,将会引发IOException。当call没有必要的时候,使用这个api可以节约网络资源。例如当用户离开一个应用时。不管同步还是异步的call都可以取消。<br>你可以通过tags来同时取消多个请求。当你构建一请求时,使用RequestBuilder.tag(tag)来分配一个标签。之后你就可以用OkHttpClient.cancel(tag)来取消所有带有这个tag的call。</p><pre class="line-numbers language-none"><code class="language-none">private final ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);private final OkHttpClient client = new OkHttpClient(); public void run() throws Exception { Request request = new Request.Builder() .url("http://httpbin.org/delay/2") // This URL is served with a 2 second delay. .build(); final long startNanos = System.nanoTime(); final Call call = client.newCall(request); // Schedule a job to cancel the call in 1 second. executor.schedule(new Runnable() { @Override public void run() { System.out.printf("%.2f Canceling call.%n", (System.nanoTime() - startNanos) / 1e9f); call.cancel(); System.out.printf("%.2f Canceled call.%n", (System.nanoTime() - startNanos) / 1e9f); } }, 1, TimeUnit.SECONDS); try { System.out.printf("%.2f Executing call.%n", (System.nanoTime() - startNanos) / 1e9f); Response response = call.execute(); System.out.printf("%.2f Call was expected to fail, but completed: %s%n", (System.nanoTime() - startNanos) / 1e9f, response); } catch (IOException e) { System.out.printf("%.2f Call failed as expected: %s%n", (System.nanoTime() - startNanos) / 1e9f, e); }}</code></pre><h2 id="超时"><a href="#超时" class="headerlink" title="超时"></a>超时</h2><p>没有响应时使用超时结束call。没有响应的原因可能是客户点链接问题、服务器可用性问题或者这之间的其他东西。OkHttp支持连接,读取和写入超时</p><pre class="line-numbers language-none"><code class="language-none">private final OkHttpClient client; public ConfigureTimeouts() throws Exception { client = new OkHttpClient(); client.setConnectTimeout(10, TimeUnit.SECONDS); client.setWriteTimeout(10, TimeUnit.SECONDS); client.setReadTimeout(30, TimeUnit.SECONDS);} public void run() throws Exception { Request request = new Request.Builder() .url("http://httpbin.org/delay/2") // This URL is served with a 2 second delay. .build(); Response response = client.newCall(request).execute(); System.out.println("Response completed: " + response);}</code></pre><h2 id="每个call的配置"><a href="#每个call的配置" class="headerlink" title="每个call的配置"></a>每个call的配置</h2><p>使用OkHttpClient,所有的HTTP Client配置包括代理设置、超时设置、缓存设置。当你需要为单个call改变配置的时候,clone 一个 OkHttpClient。这个api将会返回一个浅拷贝(shallow copy),你可以用来单独自定义。下面的例子中,我们让一个请求是500ms的超时、另一个是3000ms的超时。</p><pre class="line-numbers language-none"><code class="language-none">private final OkHttpClient client = new OkHttpClient(); public void run() throws Exception { Request request = new Request.Builder() .url("http://httpbin.org/delay/1") // This URL is served with a 1 second delay. .build(); try { Response response = client.clone() // Clone to make a customized OkHttp for this request. .setReadTimeout(500, TimeUnit.MILLISECONDS) .newCall(request) .execute(); System.out.println("Response 1 succeeded: " + response); } catch (IOException e) { System.out.println("Response 1 failed: " + e); } try { Response response = client.clone() // Clone to make a customized OkHttp for this request. .setReadTimeout(3000, TimeUnit.MILLISECONDS) .newCall(request) .execute(); System.out.println("Response 2 succeeded: " + response); } catch (IOException e) { System.out.println("Response 2 failed: " + e); }}</code></pre><h2 id="处理验证"><a href="#处理验证" class="headerlink" title="处理验证"></a>处理验证</h2><p>这部分和HTTP AUTH有关。<br>相关资料:<a href="http://blog.csdn.net/wwwsq/article/details/7255062">HTTP AUTH 那些事 - 王绍全的博客 - 博客频道 - CSDN.NET</a></p><p>OkHttp会自动重试未验证的请求。当响应是401 Not Authorized时,Authenticator会被要求提供证书。Authenticator的实现中需要建立一个新的包含证书的请求。如果没有证书可用,返回null来跳过尝试。</p><pre class="line-numbers language-none"><code class="language-none">public List<Challenge> challenges()Returns the authorization challenges appropriate for this response's code. If the response code is 401 unauthorized, this returns the "WWW-Authenticate" challenges.If the response code is 407 proxy unauthorized, this returns the "Proxy-Authenticate" challenges.Otherwise this returns an empty list of challenges.</code></pre><p>当需要实现一个Basic challenge, 使用Credentials.basic(username, password)来编码请求头。</p><pre class="line-numbers language-none"><code class="language-none">private final OkHttpClient client = new OkHttpClient(); public void run() throws Exception { client.setAuthenticator(new Authenticator() { @Override public Request authenticate(Proxy proxy, Response response) { System.out.println("Authenticating for response: " + response); System.out.println("Challenges: " + response.challenges()); String credential = Credentials.basic("jesse", "password1"); return response.request().newBuilder() .header("Authorization", credential) .build(); } @Override public Request authenticateProxy(Proxy proxy, Response response) { return null; // Null indicates no attempt to authenticate. } }); Request request = new Request.Builder() .url("http://publicobject.com/secrets/hellosecret.txt") .build(); Response response = client.newCall(request).execute(); if (!response.isSuccessful()) throw new IOException("Unexpected code " + response); System.out.println(response.body().string());}</code></pre><p>转自 <a href="http://www.cnblogs.com/ct2011/p/4001708.html">OkHttp使用介绍</a> 同时整合了 <a href="http://www.cnblogs.com/ct2011/p/3997368.html">OkHttp使用进阶</a> 这篇文章以及其中的评论。</p></form>]]></content>