From 087a2a48e1a497cbef2835d2f477032417507a7e Mon Sep 17 00:00:00 2001 From: asingularity Date: Wed, 27 Jul 2022 16:18:44 -0700 Subject: [PATCH 01/14] added webpage and compressing script --- webpage/assets/cleverpet-logo.png | Bin 0 -> 3170 bytes webpage/assets/index.3556f265.css | 1 + webpage/assets/index.42fe4937.js | 1 + webpage/assets/logo.d8ebc7ad.png | Bin 0 -> 13012 bytes webpage/create_arrays.py | 96 +++++ webpage/index_combined.html | 654 ++++++++++++++++++++++++++++++ 6 files changed, 752 insertions(+) create mode 100644 webpage/assets/cleverpet-logo.png create mode 100644 webpage/assets/index.3556f265.css create mode 100644 webpage/assets/index.42fe4937.js create mode 100644 webpage/assets/logo.d8ebc7ad.png create mode 100644 webpage/create_arrays.py create mode 100644 webpage/index_combined.html diff --git a/webpage/assets/cleverpet-logo.png b/webpage/assets/cleverpet-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..1258e401506d56418d6042ce85a4e66c80241abd GIT binary patch literal 3170 zcmai03piA17(U|`BZXMG)ihlw%!QEagrS+rCAo}2BEw9~jLe9_XeERZtq`g~qFT2$ zmsqwpt zFu@}(2EG|5PfmafgkitO94O+d41*s9Bm&;Y+8Wpa%Hn`1L>3ShK)@S-C;_7LG63v_ zC@;zO5cNfj5CFtb0Fgxu5nKU4=$bwNNcbCq?@ z2eKTMBediZ#t~kY1Q$pe#@$;jnoK)6WD>u(pF)&;v;@Jp>AY zf}28NFqmjdV0}=m?m(zAkfmakSCMkvmA-WSS$-H5Gk-A z(Fhds-)N)|%74%VmIc~;T?^ri1`4r|e~=(8Q+>3-E*&H|7?kmRq`w)L^IRY< z^Bidurm6NKqT&m$yLJzZTL-9_38^*6Hi&~Wa#`}v3BESm%2ch%72yn9h=3_zo_w<$u|G(;t=lg02 zcHM~-INxl+pg`1nb-#y}HYW!GNQQ?5O7sqNyMS5owC?}F0e4(oy-H@e$K|2e@bek9d zkgA8X2v7IJPMwbazl&Q;O#2ziw`y_BVHZWG8a4MEcTmm=<})Ztm^y=Y166llAlTy*Lz{uB-ZF4 zv8FVqWj_m%__|1M(76!Fu5~tU>3$3CP*%9&!#i>#-BY_^KR?XZW{Zn+?6IJz$j=q-W_H8F)+Fh=iH>-W{A9mGc{DBDX7xm;hnv$@-f5OaUACm=)H%(! z6L!h1(@z4;_KG+ez4B&H;G>%2({b0Gx0gPE$DWg8Pe*Ua_C53->Gk5|HK9pEM1HNz z(K3_PxG-u`cc+mp>v-s9HKrvl{ypj5u9wQQS5vC^j6ZIvydLCIyT4WuuZQR543V{T z9jrSQatOWd_bVq?i^7RPTZ@?bLJ9cv&xd>YWMwNjQk;0A$6$zFN)fb;x#$mlsKXP{qgeQ~VCksC@<1b2{Xv5-JtJ6+CK zu^OWxrPD}eI)plnN@*&~X?m3OqzG$^Id&m3>A|1YOkefhV(4`0eKWO(SJ0m3Zpwds zVuw^pcd|Nym`>!>JDg8L-RK)@xMD*4cE4grau?xjpxSoYKJ?7c-7b9(#HNSkQNB0& zRR^TZYR7wa;!&@d>o#uONM75qEzvf(Vk`BQLjQ-}gj;V~ykAtPL7S2NLiZh&lspq{ z9o}x-$EhhKJn9@HI2A}&er&sRWvI=)9l;6J%WG`ucBAErtXaPa)03;|qFFus@o{SG zhNF`F!|)j+t#zii25;nEk|opkW%eJDRxopsLj=K!(KWGWCg-AxWQFD656jzMvwNA{ z(zQ(w;zm3S>{<4=_?Zpx(NB8O(u6-W@w_yZ3-zb?B@$oRgkR$vg6h2*T{*>Ev$>Bd z*S(bwRy`Z{+5Fl0-g^y$mdiqg$U_l1o4=~H#%f0T9Z2ut^MmzM2k*{sg(u&2iN$@i zc(+<6in3>{=qG*m-sYJ}xd7$8W1~?+#Zh{(gOhmKKK<*p$Vb03E^P|S?i$#X-skAD zH~m{u^p|1y6-8*JLOh9IA`=EJJ@v@zw;$}j^ww9iDmb_aR@bO!Zo+IWDy+H*!ECNL zRva@tn5}3@YcS%X%hQUCvWke$&PWxRX=0nlKfakDzF|Ms=Lj4aUDu#Wxu*8wRFl>>Y8Lf4KvCcv~@q2p;hPxi3xl> zkPv(`ZQEL>+s{tXQlH#QStlJ(nbUzepktFKTf;tahlGyJzYmKn9L!OzYiLGl44dp; zrPR`vsG7I+%PiD;Aofc{ZLo0IwBtF7NP_dVG4{ zLn=RfNT7xLWjGE`VB{MM4zqiV24tbUkr=b;51-mgLzqbGh8pm#{ypbTo&u zTSKc>O{to`ER4_i6(brahigj8&>+M~3O)X6e<$LnW<`zq@pj2ciK_92w&QNz2i)eA YMa:not([hidden])~:not([hidden]){--tw-divide-y-reverse: 0;border-top-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px * var(--tw-divide-y-reverse))}.overflow-y-auto{overflow-y:auto}.rounded-md{border-radius:.375rem}.rounded-full{border-radius:9999px}.rounded{border-radius:.25rem}.rounded-xl{border-radius:.75rem}.border{border-width:1px}.border-2{border-width:2px}.border-0{border-width:0px}.border-b-2{border-bottom-width:2px}.border-t{border-top-width:1px}.border-b{border-bottom-width:1px}.border-indigo-500{--tw-border-opacity: 1;border-color:rgb(99 102 241 / var(--tw-border-opacity))}.border-gray-200{--tw-border-opacity: 1;border-color:rgb(229 231 235 / var(--tw-border-opacity))}.border-gray-300{--tw-border-opacity: 1;border-color:rgb(209 213 219 / var(--tw-border-opacity))}.border-transparent{border-color:transparent}.border-gray-100{--tw-border-opacity: 1;border-color:rgb(243 244 246 / var(--tw-border-opacity))}.bg-white{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity))}.bg-gray-200{--tw-bg-opacity: 1;background-color:rgb(229 231 235 / var(--tw-bg-opacity))}.bg-green-500{--tw-bg-opacity: 1;background-color:rgb(34 197 94 / var(--tw-bg-opacity))}.bg-gray-500{--tw-bg-opacity: 1;background-color:rgb(107 114 128 / var(--tw-bg-opacity))}.bg-gray-100{--tw-bg-opacity: 1;background-color:rgb(243 244 246 / var(--tw-bg-opacity))}.bg-indigo-600{--tw-bg-opacity: 1;background-color:rgb(79 70 229 / var(--tw-bg-opacity))}.bg-opacity-25{--tw-bg-opacity: .25}.p-4{padding:1rem}.p-2{padding:.5rem}.p-0{padding:0}.px-4{padding-left:1rem;padding-right:1rem}.px-1{padding-left:.25rem;padding-right:.25rem}.py-10{padding-top:2.5rem;padding-bottom:2.5rem}.px-2{padding-left:.5rem;padding-right:.5rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.pt-1{padding-top:.25rem}.pt-5{padding-top:1.25rem}.pr-4{padding-right:1rem}.text-center{text-align:center}.text-sm{font-size:.875rem;line-height:1.25rem}.text-4xl{font-size:2.25rem;line-height:2.5rem}.text-xs{font-size:.75rem;line-height:1rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.font-medium{font-weight:500}.font-bold{font-weight:700}.font-thin{font-weight:100}.text-gray-900{--tw-text-opacity: 1;color:rgb(17 24 39 / var(--tw-text-opacity))}.text-green-400{--tw-text-opacity: 1;color:rgb(74 222 128 / var(--tw-text-opacity))}.text-gray-500{--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity))}.text-gray-300{--tw-text-opacity: 1;color:rgb(209 213 219 / var(--tw-text-opacity))}.text-green-600{--tw-text-opacity: 1;color:rgb(22 163 74 / var(--tw-text-opacity))}.text-gray-700{--tw-text-opacity: 1;color:rgb(55 65 81 / var(--tw-text-opacity))}.text-red-500{--tw-text-opacity: 1;color:rgb(239 68 68 / var(--tw-text-opacity))}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}.text-green-500{--tw-text-opacity: 1;color:rgb(34 197 94 / var(--tw-text-opacity))}.text-gray-800{--tw-text-opacity: 1;color:rgb(31 41 55 / var(--tw-text-opacity))}.text-red-300{--tw-text-opacity: 1;color:rgb(252 165 165 / var(--tw-text-opacity))}.placeholder-gray-500::-moz-placeholder{--tw-placeholder-opacity: 1;color:rgb(107 114 128 / var(--tw-placeholder-opacity))}.placeholder-gray-500:-ms-input-placeholder{--tw-placeholder-opacity: 1;color:rgb(107 114 128 / var(--tw-placeholder-opacity))}.placeholder-gray-500::placeholder{--tw-placeholder-opacity: 1;color:rgb(107 114 128 / var(--tw-placeholder-opacity))}.shadow{--tw-shadow: 0 1px 3px 0 rgb(0 0 0 / .1), 0 1px 2px -1px rgb(0 0 0 / .1);--tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-sm{--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-2xl{--tw-shadow: 0 25px 50px -12px rgb(0 0 0 / .25);--tw-shadow-colored: 0 25px 50px -12px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.ring-0{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.ring-1{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.ring-black{--tw-ring-opacity: 1;--tw-ring-color: rgb(0 0 0 / var(--tw-ring-opacity))}.ring-opacity-5{--tw-ring-opacity: .05}.transition-colors{transition-property:color,background-color,border-color,fill,stroke,-webkit-text-decoration-color;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,-webkit-text-decoration-color;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition{transition-property:color,background-color,border-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-text-decoration-color,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-text-decoration-color,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-200{transition-duration:.2s}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}.page-bg{background-color:#e5e5e5}.focus\:border-indigo-500:focus{--tw-border-opacity: 1;border-color:rgb(99 102 241 / var(--tw-border-opacity))}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-2:focus{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus\:ring-0:focus{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus\:ring-green-500:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(34 197 94 / var(--tw-ring-opacity))}.focus\:ring-indigo-500:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(99 102 241 / var(--tw-ring-opacity))}.focus\:ring-offset-2:focus{--tw-ring-offset-width: 2px}@media (min-width: 640px){.sm\:ml-6{margin-left:1.5rem}.sm\:flex{display:flex}.sm\:w-1\/2{width:50%}.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:space-x-8>:not([hidden])~:not([hidden]){--tw-space-x-reverse: 0;margin-right:calc(2rem * var(--tw-space-x-reverse));margin-left:calc(2rem * calc(1 - var(--tw-space-x-reverse)))}.sm\:p-6{padding:1.5rem}.sm\:px-6{padding-left:1.5rem;padding-right:1.5rem}.sm\:text-sm{font-size:.875rem;line-height:1.25rem}}@media (min-width: 768px){.md\:h-20{height:5rem}.md\:w-20{width:5rem}.md\:p-20{padding:5rem}.md\:py-5{padding-top:1.25rem;padding-bottom:1.25rem}.md\:text-2xl{font-size:1.5rem;line-height:2rem}.md\:text-7xl{font-size:4.5rem;line-height:1}.md\:text-xl{font-size:1.25rem;line-height:1.75rem}}@media (min-width: 1024px){.lg\:px-8{padding-left:2rem;padding-right:2rem}} diff --git a/webpage/assets/index.42fe4937.js b/webpage/assets/index.42fe4937.js new file mode 100644 index 0000000..c9883e1 --- /dev/null +++ b/webpage/assets/index.42fe4937.js @@ -0,0 +1 @@ +const s=function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const e of document.querySelectorAll('link[rel="modulepreload"]'))n(e);new MutationObserver(e=>{for(const r of e)if(r.type==="childList")for(const o of r.addedNodes)o.tagName==="LINK"&&o.rel==="modulepreload"&&n(o)}).observe(document,{childList:!0,subtree:!0});function i(e){const r={};return e.integrity&&(r.integrity=e.integrity),e.referrerpolicy&&(r.referrerPolicy=e.referrerpolicy),e.crossorigin==="use-credentials"?r.credentials="include":e.crossorigin==="anonymous"?r.credentials="omit":r.credentials="same-origin",r}function n(e){if(e.ep)return;e.ep=!0;const r=i(e);fetch(e.href,r)}};s(); diff --git a/webpage/assets/logo.d8ebc7ad.png b/webpage/assets/logo.d8ebc7ad.png new file mode 100644 index 0000000000000000000000000000000000000000..ffade0df87989bb6a59130bcf1b2405cd2529078 GIT binary patch literal 13012 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 BN8JDb literal 0 HcmV?d00001 diff --git a/webpage/create_arrays.py b/webpage/create_arrays.py new file mode 100644 index 0000000..ab79699 --- /dev/null +++ b/webpage/create_arrays.py @@ -0,0 +1,96 @@ + + + +import sys +import os +import subprocess + + +def main(): + + N_arrays = 40 + # TODO THIS IS JUST A SIZE EXPERIMENT! + # THIS WON'T WORK ON PARTICLE + # IT REFERENCES .css, .js that are not included! + # testing whether size is good, how much remains, if those are assumed loaded from elsewhere + # we will need text version backup in this case + + #input_file = 'cleverpet_minified/index.html' + + input_file = 'index_combined.html' + + # use work folder + + whole_string = '' + #lines = [] + f = open(input_file, 'r') + + all_cpp_lines = '' + + done = False + while not done: + line = f.readline() + + # strip out whitespace at start of line + line = line.lstrip(' ') + + #print(int(line[-1])) + if line: + #lines.append(line) + whole_string += line + else: + done = True + + print(len(whole_string)) + + chars_per_array = int(len(whole_string) / N_arrays) + + for k in range(N_arrays): + # print this section to a tmp html file + tmp_html_file = 'work/html_piece_' + str(k) + '.tmp' + tmp_out_file = 'work/cpp_piece_' + str(k) + '.h' + f_out = open(tmp_html_file, 'w') + + l_start = k * chars_per_array + l_end = (k + 1) * chars_per_array + + if k == N_arrays - 1: + l_end = len(whole_string) + + print(l_start, l_end, l_end-l_start) + + lines_to_write = whole_string[l_start:l_end] + f_out.write(lines_to_write) + f_out.close() + + # run bin2c + subprocess.run(["bin2c", "-H", tmp_out_file, tmp_html_file]) + + # load line and append to all lines + f2 = open(tmp_out_file, 'r') + code_line = None + for line in f2.readlines(): + if line.startswith('static const unsigned char'): + code_line = line + code_line = code_line.replace('static const unsigned char', 'static const char') + + if code_line is not None: + all_cpp_lines += code_line + else: + print("ERROESJPOGJSIOPDGOSDHGIOHSDIGHSDUIGIZXSDJBGHSDUIHGJUISDHGFUIOSDBH!@!!!!!!") + assert False + + f.close() + + f = open('complete_html_code.h', 'w') + f.write(all_cpp_lines) + f.close() + + + for k in range(N_arrays): + #print('Log.info(bin2c_html_piece_' + str(k) + '_tmp);') + print('_webclient.print(bin2c_html_piece_' + str(k) + '_tmp);') + + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/webpage/index_combined.html b/webpage/index_combined.html new file mode 100644 index 0000000..5d7866a --- /dev/null +++ b/webpage/index_combined.html @@ -0,0 +1,654 @@ + + + + + + + Clever Pet + + + + + + + +
+
+
+
+
+ + + +

+ You hub status is active +

+
+
+

30

+

+ Kibbles eaten today +

+
+
+
+ +
+ Date and Time settings +
+
+
+
+
+

Date and Time

+ Wed Mar 23 2022 23:40:11 +
+
+
+
+
+
+

Apply Daylight Savings

+ + +
+
+
+
+
+
+

Timezone

+

America/Los Angeles

+ +
+
+
+
+
+
+
+
+ + +
+ +
+ + +
+
+ + +
+
+
+
+
+ +
+ +
+ Kibbles settings +
+
+
+
+
+

Max Kibbles Per Day

+

40

+ +
+
+
+
+
+
+ +
+ Select Game +
+
+
+
    +
  • +
    + +
    +

    Eating the food

    +

    +
    +
    +
  • +
  • +
    + +
    +

    Exploring the Touchpads

    +

    +
    +
    +
  • +
  • +
    + +
    +

    Engaging Consistently

    +

    +
    +
    +
  • +
  • +
    + +
    +

    Avoiding Unlit Touchpads

    +

    +
    +
    +
  • +
  • +
    + +
    +

    Learning the Lights

    +

    +
    +
    +
  • +
  • +
    + +
    +

    Mastering the Lights

    +

    +
    +
    +
  • +
  • +
    + +
    +

    Responding Quickly

    +

    +
    +
    +
  • +
  • +
    + +
    +

    Learning Brightness

    +

    +
    +
    +
  • +
  • +
    + +
    +

    Learning Double Sequences

    +

    +
    +
    +
  • +
  • +
    + +
    +

    Learning Longer Sequences

    +

    +
    +
    +
  • +
  • +
    + +
    +

    Matching Two Colors

    +

    +
    +
    +
  • +
  • +
    + +
    +

    Matching More Colors

    +

    +
    +
    +
  • +
+
+
+
+
+ + + + + + + + + + + + + From eb3b33f9298584ca0b130d5fe5cdb8a5e9a9d229 Mon Sep 17 00:00:00 2001 From: asingularity Date: Wed, 27 Jul 2022 16:55:38 -0700 Subject: [PATCH 02/14] rename main file --- examples/main/{particle-test-local.ino => hackerpet_plus.ino} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename examples/main/{particle-test-local.ino => hackerpet_plus.ino} (98%) diff --git a/examples/main/particle-test-local.ino b/examples/main/hackerpet_plus.ino similarity index 98% rename from examples/main/particle-test-local.ino rename to examples/main/hackerpet_plus.ino index 54ffd78..3e394f6 100644 --- a/examples/main/particle-test-local.ino +++ b/examples/main/hackerpet_plus.ino @@ -1,5 +1,5 @@ /* - * Project particle-test-local + * Project hackerpet_plus * Description: * Author: * Date: From f8cfa7e238c6391e328e7bc338472dd33080242f Mon Sep 17 00:00:00 2001 From: asingularity Date: Sun, 14 Aug 2022 17:50:12 -0700 Subject: [PATCH 03/14] some cleanup, documentation --- examples/main/hackerpet_plus.ino | 9 ++-- src/config-manager.cpp | 53 ++++++++++++------------ src/config-manager.h | 71 ++++++++++++++++---------------- 3 files changed, 67 insertions(+), 66 deletions(-) diff --git a/examples/main/hackerpet_plus.ino b/examples/main/hackerpet_plus.ino index 3e394f6..d85b9dc 100644 --- a/examples/main/hackerpet_plus.ino +++ b/examples/main/hackerpet_plus.ino @@ -31,6 +31,8 @@ STARTUP(softap_set_application_page_handler(myPages, nullptr)); void setup() { configMan.Initialize(); // also initializes game manager + + // this is used by hackerpet for reports hub.Initialize("game_ID_here_TODO"); // in games it was: hub.Initialize(__FILE__); } @@ -44,20 +46,19 @@ void loop() { // serve webpage, read/write eeprom as config changes configMan.Run(); - // ************************************ DISABLE FOR TESTING WITHOUT HUB ************************************ // run the hub + // if testing on a particle photon by itself with no hub, comment this line to avoid seg fault hub.Run(20); - // ************************************ ************************************ ************************************ // run the loop for the current active game gameMan.Run(); FREE_MEMORY = System.freeMemory(); - + + // every 10 seconds, print the free memory as a serial heartbeat if ((millis() - lastmemcheck) > 10000) { lastmemcheck = millis(); Serial.print(Time.timeStr()); - Serial.println("in7399"); Serial.printlnf("\tMILLIS: %lu\tSYSTEM MEMORY=%lu", lastmemcheck, FREE_MEMORY); } } diff --git a/src/config-manager.cpp b/src/config-manager.cpp index 97086d3..bd4a97a 100644 --- a/src/config-manager.cpp +++ b/src/config-manager.cpp @@ -21,7 +21,7 @@ ConfigManager::ConfigManager(HubInterface * hub, GameManager * gameMan) bool ConfigManager::_sched_char_to_string(char * char_tmp, String & str) { - + // utility to convert char to string, for scheduler String str2(char_tmp); str = str2; return true; @@ -29,6 +29,7 @@ bool ConfigManager::_sched_char_to_string(char * char_tmp, String & str) bool ConfigManager::_sched_string_to_char(char * char_tmp, String & str) { + // utility to convert string to char, for scheduler for (int k = 0; k < 5; k++) { char_tmp[k] = str[k]; @@ -40,7 +41,10 @@ bool ConfigManager::Initialize() { _system_ready = false; - bool ever_stored = false; // have we ever stored a game to eeprom? check value against "checksum" + bool ever_stored = false; // have we ever stored a game to eeprom? + + // we check against a hard coded value, and if there's no match, we assume we need to initialize all the EEPROM values to defaults for this hub + uint16_t ever_stored_check; EEPROM.get(_EVER_STORED_EEP_ADDRESS, ever_stored_check); @@ -50,11 +54,12 @@ bool ConfigManager::Initialize() } if (ever_stored) - { + { + // assume this hub's eeprom has been initialied at least once and all values can be read: + EEPROM.get(_GAME_EEP_ADDRESS, _game_to_play); _next_game_to_play = _game_to_play; _gameMan->Initialize(_next_game_to_play); - //_gameMan->set_next_game(_next_game_to_play); EEPROM.get(_TIME_ZONE_EEP_ADDRESS, _time_zone_offset); Time.zone(_time_zone_offset); @@ -96,17 +101,17 @@ bool ConfigManager::Initialize() } else { - // default values for a "new" hub: + // assume this hub's eeprom has not been initialized, or the hard coded value was changed to force a reset to defaults: + _game_to_play = 0; _next_game_to_play = 0; - _time_zone_offset = 0.0; // TIME_ZONE_OFFSET = 0.0; - _dst_on = false; // DST_ON = false; - _hub_mode = _HUB_MODE_STAY_ON; // HUB_MODE = HUB_MODE_STAY_ON; + _time_zone_offset = 0.0; + _dst_on = false; + _hub_mode = _HUB_MODE_STAY_ON; EEPROM.put(_GAME_EEP_ADDRESS, _next_game_to_play); _gameMan->Initialize(_next_game_to_play); - //_gameMan->set_next_game(_next_game_to_play); EEPROM.put(_TIME_ZONE_EEP_ADDRESS, _time_zone_offset); Time.zone(_time_zone_offset); @@ -148,6 +153,7 @@ bool ConfigManager::Initialize() // to force initialization to a valid _hub_state in Run() _hub_state = _HUB_STATE_INIT; + // mdns for http server mgschwan_mdns = new MDNS; return true; @@ -157,15 +163,14 @@ bool ConfigManager::Initialize() bool ConfigManager::Run() { - // interface + // this function is the interface: // of config / parameters from config manager above, to game manager and hub below // also other way around, from hub to config manager for webpage display - // TODO: set Hub mode based on _hub_mode !!! use _hub - - if (WiFi.ready() && _system_ready == false) { + // set up mdns for the local http server + delete mgschwan_mdns; mgschwan_mdns = new MDNS; @@ -183,13 +188,16 @@ bool ConfigManager::Run() if (_system_ready) { + // it's not clear if this can/should be called less or more often; + // the webserver appears more stable on some hubs with mdns being called every second, instead of every loop + // this should be investigated further... if ((millis() - _last_mdns_loop_time)>1000) { - //Serial.println(" >>>>>>>> Calling mgschwan_MDNS_loop ... >>>>>>>>"); mgschwan_MDNS_loop(mgschwan_mdns); - //Serial.println(" >>>>>>>> Done calling mgschwan_MDNS_loop. >>>>>>>>"); _last_mdns_loop_time = millis(); } + + // what message to display on the webpage for hub status _display_error_msg = "Your hub is working."; if (_hub->IsHubOutOfFood()) @@ -209,7 +217,7 @@ bool ConfigManager::Run() _display_error_msg = "Dome is removed."; } - // get current game from gameMan + // get current game from game manager _game_to_play = _gameMan->get_current_game(); _new_game_selected = _game_to_play; @@ -227,8 +235,9 @@ bool ConfigManager::Run() } - // test idea that we always attempt to reconnect every N seconds. - // could make this last webpage-request dependent, so if webpage is currently active, don't need to do this + // on some networks, mdns occasionally fails and the domain clevepet.local stops working; need to attempt reconnect + // since we don't have a conclusive way to determine if it is broken, we for now blindly attempt reconnect every 10 seconds if there's no request in that time + bool _need_mdns_reconnect = (millis() - _last_request_time > 10000); if (_need_mdns_reconnect) @@ -240,9 +249,6 @@ bool ConfigManager::Run() Serial.print(Time.timeStr()); Serial.println(" ######## Attempting mdns reconnect... ########"); - //delete mgschwan_mdns; - //mgschwan_mdns = new MDNS; - _broadcastAddress = mgschwan_getBroadcastAddress(); mgschwan_setupNetwork(mgschwan_mdns, true); @@ -253,11 +259,6 @@ bool ConfigManager::Run() } - // TODO should _process_hub_mode be outside system_ready? things should function in general even if not on wifi??? - // also set to active by default? - // TODO it already is by default but should set back to HUB STAY ON mode if can't connect to wifi??? or at least not in HUB STAY OFF mode??? - // also... we might need to put this in its own class at some point - _process_hub_mode(); return true; diff --git a/src/config-manager.h b/src/config-manager.h index 3c670a9..76b8144 100644 --- a/src/config-manager.h +++ b/src/config-manager.h @@ -11,11 +11,6 @@ using namespace mdns; #include "html-manager.h" -// TODO ADD THIS FILE TO GIT - -// TODO also need to commit hackerpet changes separately!!! - - class ConfigManager { public: @@ -23,22 +18,22 @@ class ConfigManager bool Initialize(); bool Run(); private: - bool _sched_char_to_string(char * char_tmp, String & str); - bool _sched_string_to_char(char * char_tmp, String & str); - bool _process_hub_mode(); - bool _serve_webinterface(); - bool _read_from_client(bool & request_finished, String & response_str); - bool _process_request(String req_str); - bool _process_api_get_req(String req_str); - bool _process_api_post_req(String req_str); - bool _process_set_game_req(String req_str); //, int dst_index); - bool _process_set_max_kibbles_req(String req_str); - bool _process_set_kibbles_thresh_req(String req_str); - bool _process_set_dst_req(String req_str); //, int dst_index); - bool _process_set_timezone_req(String req_str); // , int dst_index); - bool _process_set_hub_mode_req(String req_str); //, int dst_index); - bool _process_set_schedule_req(String req_str); - bool _process_get_req(String req_str); + bool _sched_char_to_string(char * char_tmp, String & str); // utility to convert char to string, for scheduler + bool _sched_string_to_char(char * char_tmp, String & str); // utility to convert string to char, for scheduler + bool _process_hub_mode(); // set new hub mode (on/off/scheduler), if needed, and then set hub state (on/standby) based on scheduler if applicable + bool _serve_webinterface(); // serves local http server + bool _read_from_client(bool & request_finished, String & response_str); // read a request + bool _process_request(String req_str); // process an http request + bool _process_api_get_req(String req_str); // process an API request from cleverpet.local + bool _process_api_post_req(String req_str); // post request + bool _process_set_game_req(String req_str); // a request to set a game to play + bool _process_set_max_kibbles_req(String req_str); // set max kibbles + bool _process_set_kibbles_thresh_req(String req_str); // set kibbles detection threshold + bool _process_set_dst_req(String req_str); // set daylight saving time on/off + bool _process_set_timezone_req(String req_str); // set the timezone + bool _process_set_hub_mode_req(String req_str); // set a new hub mode + bool _process_set_schedule_req(String req_str); // set scheduler settings + bool _process_get_req(String req_str); // http get request for showing cleverpet.local webpage HubInterface * _hub; GameManager * _gameMan; @@ -53,11 +48,11 @@ class ConfigManager // ***************** const EEPROM addresses ***************** - const int _EVER_STORED_EEP_ADDRESS = 10; // EVER_STORED_ADDRESS = 10; - const int _GAME_EEP_ADDRESS = 20; // GAME_ADDRESS = 20; - const int _TIME_ZONE_EEP_ADDRESS = 30; // TIME_ZONE_ADDRESS = 30; - const int _DST_EEP_ADDRESS = 40; // DST_ADDRESS = 40; - const int _HUB_MODE_EEP_ADDRESS = 50; // HUB_MODE_ADDRESS = 50; + const int _EVER_STORED_EEP_ADDRESS = 10; + const int _GAME_EEP_ADDRESS = 20; + const int _TIME_ZONE_EEP_ADDRESS = 30; + const int _DST_EEP_ADDRESS = 40; + const int _HUB_MODE_EEP_ADDRESS = 50; const int _SCHED_WEEKDAY_FROM_ADDRESS = 60; const int _SCHED_WEEKDAY_TO_ADDRESS = 160; const int _SCHED_WEEKEND_FROM_ADDRESS = 260; @@ -66,8 +61,9 @@ class ConfigManager // ***************** const other ***************** - // we can change this number to force an eeprom "reset" to defaults; and to avoid undefined state when adding new variables - const int _EVER_STORED_CHECK_VALUE = 12357; // EVER_STORED_CHECK_VALUE = 12346; + // if this number does not match the number stored at EEPROM address _EVER_STORED_EEP_ADDRESS, eeprom will be "reset" to defaults + // this number should be changed to avoid an undefined value at any new addresses added above + const int _EVER_STORED_CHECK_VALUE = 12357; const int _HUB_MODE_STAY_OFF = 0; const int _HUB_MODE_STAY_ON = 1; @@ -78,19 +74,21 @@ class ConfigManager const int _HUB_STATE_INIT = 2; // to force initialization // ***************** config vars ***************** - + + // these are variables set by the user via the cleverpet.local web page and local http server + int _hub_mode; // _HUB_MODE_STAY_OFF, _HUB_MODE_STAY_ON, _HUB_MODE_SCHEDULED int _last_hub_mode; - int _hub_state; // _HUB_STATE_STANDBY, _HUB_STATE_ACTIVE + int _hub_state; // _HUB_STATE_STANDBY, _HUB_STATE_ACTIVE, _HUB_STATE_INIT - int _game_to_play; // GAME_TO_PLAY; - int _next_game_to_play; // NEXT_GAME_TO_PLAY; - int _new_game_selected; // selected (clicked) via web interface + int _game_to_play; + int _next_game_to_play; + int _new_game_selected; - float _time_zone_offset; // TIME_ZONE_OFFSET = 0.0; - bool _dst_on; // DST_ON = false; + float _time_zone_offset; + bool _dst_on; String _weekday_from; String _weekday_to; @@ -103,7 +101,8 @@ class ConfigManager int _kibbles_eaten_today; int _last_day; - + + // mdns reconnect variables unsigned long _last_mdns_reconnect_attempt; unsigned long _last_request_time; MDNS * mgschwan_mdns; From 60b372ed111905395b9cfc617520682a2f340b94 Mon Sep 17 00:00:00 2001 From: asingularity Date: Tue, 20 Sep 2022 14:00:25 -0700 Subject: [PATCH 04/14] debugging freeze bug --- examples/main/particle-test-local.ino | 33 +++++++++++++++------------ library.properties | 6 ++--- src/config-manager.cpp | 13 +++++++---- src/game-manager.cpp | 2 ++ 4 files changed, 33 insertions(+), 21 deletions(-) diff --git a/examples/main/particle-test-local.ino b/examples/main/particle-test-local.ino index 54ffd78..0086008 100644 --- a/examples/main/particle-test-local.ino +++ b/examples/main/particle-test-local.ino @@ -40,24 +40,29 @@ unsigned long FREE_MEMORY; // loop() runs over and over again, as quickly as it can execute. void loop() { - - // serve webpage, read/write eeprom as config changes - configMan.Run(); - // ************************************ DISABLE FOR TESTING WITHOUT HUB ************************************ - // run the hub - hub.Run(20); - // ************************************ ************************************ ************************************ + if ((millis() - lastmemcheck) > 1000) { + // serve webpage, read/write eeprom as config changes + Serial.println("[[calling]]: configMan.Run();"); + configMan.Run(); + + // ************************************ DISABLE FOR TESTING WITHOUT HUB ************************************ + // run the hub + Serial.println("[[calling]]: hub.Run(20);"); + hub.Run(20); + // ************************************ ************************************ ************************************ - // run the loop for the current active game - gameMan.Run(); + // run the loop for the current active game + Serial.println("[[calling]]: gameMan.Run();"); + gameMan.Run(); - FREE_MEMORY = System.freeMemory(); - - if ((millis() - lastmemcheck) > 10000) { - lastmemcheck = millis(); Serial.print(Time.timeStr()); - Serial.println("in7399"); + Serial.println("[[calling]]: free memory"); + + FREE_MEMORY = System.freeMemory(); + + lastmemcheck = millis(); + Serial.printlnf("\tMILLIS: %lu\tSYSTEM MEMORY=%lu", lastmemcheck, FREE_MEMORY); } } diff --git a/library.properties b/library.properties index 4e79420..c59c218 100644 --- a/library.properties +++ b/library.properties @@ -1,9 +1,9 @@ -name=hackerpet_plus -version=0.1.110 +name=hackerpet_plus_dev +version=0.1.53 license=AGPL author=Csaba Petre maintainer=Csaba Petre -sentence=(Alpha Version!) Long-term cloud-less firmware! +sentence=(Dev Version!) Long-term cloud-less firmware! category=Other url=http://hackerpet.com repository=https://github.com/CleverPet/hackerpet_plus/ diff --git a/src/config-manager.cpp b/src/config-manager.cpp index 97086d3..5ca76c3 100644 --- a/src/config-manager.cpp +++ b/src/config-manager.cpp @@ -185,12 +185,13 @@ bool ConfigManager::Run() { if ((millis() - _last_mdns_loop_time)>1000) { - //Serial.println(" >>>>>>>> Calling mgschwan_MDNS_loop ... >>>>>>>>"); + Serial.println(" >>>>>>>> Calling mgschwan_MDNS_loop ... >>>>>>>>"); mgschwan_MDNS_loop(mgschwan_mdns); - //Serial.println(" >>>>>>>> Done calling mgschwan_MDNS_loop. >>>>>>>>"); + Serial.println(" >>>>>>>> Done calling mgschwan_MDNS_loop. >>>>>>>>"); _last_mdns_loop_time = millis(); } + Serial.println(" [[ConfigManager::Run()]]: 1!"); _display_error_msg = "Your hub is working."; if (_hub->IsHubOutOfFood()) { @@ -209,12 +210,15 @@ bool ConfigManager::Run() _display_error_msg = "Dome is removed."; } + Serial.println(" [[ConfigManager::Run()]]: 2!"); // get current game from gameMan _game_to_play = _gameMan->get_current_game(); _new_game_selected = _game_to_play; + Serial.println(" [[ConfigManager::Run()]]: 3!"); _serve_webinterface(); + Serial.println(" [[ConfigManager::Run()]]: 4!"); if (_new_game_selected >= 0 && _new_game_selected != _game_to_play) { Log.info("New game selected %i", _new_game_selected); @@ -227,6 +231,7 @@ bool ConfigManager::Run() } + Serial.println(" [[ConfigManager::Run()]]: 5!"); // test idea that we always attempt to reconnect every N seconds. // could make this last webpage-request dependent, so if webpage is currently active, don't need to do this bool _need_mdns_reconnect = (millis() - _last_request_time > 10000); @@ -257,9 +262,9 @@ bool ConfigManager::Run() // also set to active by default? // TODO it already is by default but should set back to HUB STAY ON mode if can't connect to wifi??? or at least not in HUB STAY OFF mode??? // also... we might need to put this in its own class at some point - + Serial.println(" [[ConfigManager::Run()]]: 6!"); _process_hub_mode(); - + Serial.println(" [[ConfigManager::Run()]]: 7!"); return true; } diff --git a/src/game-manager.cpp b/src/game-manager.cpp index 7ba790a..f92debf 100644 --- a/src/game-manager.cpp +++ b/src/game-manager.cpp @@ -67,6 +67,7 @@ bool GameManager::Run() { if (_game_enabled) { + Serial.println(" [[GameManager::Run()]]: 1!"); bool trial_done = false; // TODO simplify this / move to a function when cleaning up @@ -141,6 +142,7 @@ bool GameManager::Run() } _trial_just_done = trial_done; + Serial.println(" [[GameManager::Run()]]: 2!"); } else { From f9171c3044e2746d8c7abf9d00f48d4937edc576 Mon Sep 17 00:00:00 2001 From: asingularity Date: Tue, 20 Sep 2022 16:42:18 -0700 Subject: [PATCH 05/14] debugging mdns locally --- examples/main/particle-test-local.ino | 9 + lib/MDNS/src/Buffer.cpp | 73 +++++++ lib/MDNS/src/Buffer.h | 46 ++++ lib/MDNS/src/Label.cpp | 299 ++++++++++++++++++++++++++ lib/MDNS/src/Label.h | 149 +++++++++++++ lib/MDNS/src/MDNS.cpp | 282 ++++++++++++++++++++++++ lib/MDNS/src/MDNS.h | 68 ++++++ lib/MDNS/src/Record.cpp | 165 ++++++++++++++ lib/MDNS/src/Record.h | 157 ++++++++++++++ library.properties | 3 +- project.properties | 1 - src/config-manager.cpp | 2 +- src/config-manager.h | 2 +- src/http-server-util.cpp | 3 +- src/http-server-util.h | 2 +- 15 files changed, 1254 insertions(+), 7 deletions(-) create mode 100644 lib/MDNS/src/Buffer.cpp create mode 100644 lib/MDNS/src/Buffer.h create mode 100644 lib/MDNS/src/Label.cpp create mode 100644 lib/MDNS/src/Label.h create mode 100644 lib/MDNS/src/MDNS.cpp create mode 100644 lib/MDNS/src/MDNS.h create mode 100644 lib/MDNS/src/Record.cpp create mode 100644 lib/MDNS/src/Record.h diff --git a/examples/main/particle-test-local.ino b/examples/main/particle-test-local.ino index 0086008..5587985 100644 --- a/examples/main/particle-test-local.ino +++ b/examples/main/particle-test-local.ino @@ -11,6 +11,15 @@ #include "softap_http.h" #include "hotspot-http-server.h" +# include "../lib/MDNS/src/Buffer.h" +# include "../lib/MDNS/src/Buffer.cpp" +# include "../lib/MDNS/src/Record.h" +# include "../lib/MDNS/src/Record.cpp" +# include "../lib/MDNS/src/Label.h" +# include "../lib/MDNS/src/Label.cpp" +# include "../lib/MDNS/src/MDNS.h" +# include "../lib/MDNS/src/MDNS.cpp" + // new #include "config-manager.h" diff --git a/lib/MDNS/src/Buffer.cpp b/lib/MDNS/src/Buffer.cpp new file mode 100644 index 0000000..07c5b65 --- /dev/null +++ b/lib/MDNS/src/Buffer.cpp @@ -0,0 +1,73 @@ +#include "Buffer.h" + +mdns::Buffer::Buffer(uint16_t size) { + this->data = (uint8_t *) malloc(size); + this->size = data != NULL? size : 0; +} + +uint16_t mdns::Buffer::available() { + return offset < limit? limit - offset : offset - limit; +} + +void mdns::Buffer::mark() { + if (markOffset == INVALID_MARK_OFFSET) { + markOffset = offset; + } +} + +void mdns::Buffer::reset() { + if (markOffset != INVALID_MARK_OFFSET) { + offset = markOffset; + markOffset = INVALID_MARK_OFFSET; + } +} + +void mdns::Buffer::setOffset(uint16_t offset) { + this->offset = offset; +} + +uint16_t mdns::Buffer::getOffset() { + return offset; +} + +void mdns::Buffer::read(UDP * udp) { + offset = 0; + limit = udp->read(data, size); +} + +uint8_t mdns::Buffer::readUInt8() { + return data[offset++]; +} + +uint16_t mdns::Buffer::readUInt16() { + return readUInt8() << 8 | readUInt8(); +} + +void mdns::Buffer::writeUInt8(uint8_t value) { + if (offset < size) { + data[offset++] = value; + } +} + +void mdns::Buffer::writeUInt16(uint16_t value) { + writeUInt8(value >> 8); + writeUInt8(value); +} + +void mdns::Buffer::writeUInt32(uint32_t value) { + writeUInt8(value >> 24); + writeUInt8(value >> 16); + writeUInt8(value >> 8); + writeUInt8(value); +} + +void mdns::Buffer::write(UDP * udp) { + udp->write(data, offset); + + offset = 0; +} + +void mdns::Buffer::clear() { + offset = 0; + limit = 0; +} diff --git a/lib/MDNS/src/Buffer.h b/lib/MDNS/src/Buffer.h new file mode 100644 index 0000000..16d27b0 --- /dev/null +++ b/lib/MDNS/src/Buffer.h @@ -0,0 +1,46 @@ +#include "application.h" + +#ifndef _INCL_BUFFER +#define _INCL_BUFFER + +#define INVALID_MARK_OFFSET 0xffff + +namespace mdns { + + class Buffer { + public: + Buffer(uint16_t size); + + uint16_t available(); + + void mark(); + void reset(); + void setOffset(uint16_t offset); + uint16_t getOffset(); + + void read(UDP * udp); + + uint8_t readUInt8(); + uint16_t readUInt16(); + + void write(UDP * udp); + + void writeUInt8(uint8_t value); + void writeUInt16(uint16_t value); + void writeUInt32(uint32_t value); + + void clear(); + + private: + + uint8_t * data; + uint16_t size; + + uint16_t limit = 0; + uint16_t offset = 0; + uint16_t markOffset = INVALID_MARK_OFFSET; + }; + +} + +#endif diff --git a/lib/MDNS/src/Label.cpp b/lib/MDNS/src/Label.cpp new file mode 100644 index 0000000..ca8babe --- /dev/null +++ b/lib/MDNS/src/Label.cpp @@ -0,0 +1,299 @@ +#include "Label.h" + +mdns::Label::Label(String name, Label * nextLabel, bool caseSensitive) { + data = (uint8_t *) malloc(name.length() + 1); + + if (data) { + data[0] = name.length(); + for (uint8_t i = 0; i < name.length(); i++) { + data[i + 1] = name.charAt(i); + } + } else { + data = EMPTY_DATA; + } + + this->nextLabel = nextLabel; + this->caseSensitive = caseSensitive; +} + +uint8_t mdns::Label::getSize() { + return data[0]; +} + +uint8_t mdns::Label::getWriteSize() { + Label * label = this; + uint8_t size = 0; + + while (label != NULL) { + if (label->writeOffset == INVALID_OFFSET) { + size += label->data[0] + 1; + label = label->nextLabel; + } else { + size += 2; + label = NULL; + } + } + + return size; +} + +void mdns::Label::write(Buffer * buffer) { + Label * label = this; + + while (label) { + if (label->writeOffset == INVALID_OFFSET) { + label->writeOffset = buffer->getOffset(); + + uint8_t size = label->data[0] + 1; + + for (uint8_t i = 0; i < size; i++) { + buffer->writeUInt8(label->data[i]); + } + + label = label->nextLabel; + } else { + buffer->writeUInt16((LABEL_POINTER << 8) | label->writeOffset); + label = NULL; + } + } +} + +void mdns::Label::reset() { + Label * label = this; + + while (label != NULL) { + label->writeOffset = INVALID_OFFSET; + + label = label->nextLabel; + } +} + +mdns::Label::Reader::Reader(Buffer * buffer) { + this->buffer = buffer; +} + +bool mdns::Label::Reader::hasNext() { + return c != END_OF_NAME && buffer->available() > 0; +} + +uint8_t mdns::Label::Reader::next() { + c = buffer->readUInt8(); + + while ((c & LABEL_POINTER) == LABEL_POINTER) { + if (buffer->available() > 0) { + uint8_t c2 = buffer->readUInt8(); + + uint16_t pointerOffset = ((c & ~LABEL_POINTER) << 8) | c2; + + buffer->mark(); + + buffer->setOffset(pointerOffset); + + c = buffer->readUInt8(); + } + } + + return c; +} + +bool mdns::Label::Reader::endOfName() { + return c == END_OF_NAME; +} + +mdns::Label::Iterator::Iterator(Label * label) { + this->label = label; + this->startLabel = label; + this->size = label->data[0]; +} + +bool mdns::Label::Iterator::match(uint8_t c) { + if (matches) { + while (offset > size && label) { + label = label->nextLabel; + size = label->data[0]; + offset = 0; + } + + matches = offset <= size && label && (label->data[offset] == c || (!label->caseSensitive && equalsIgnoreCase(c))); + + offset++; + } + + return matches; +} + +bool mdns::Label::Iterator::matched() { + return matches; +} + +bool mdns::Label::Iterator::equalsIgnoreCase(uint8_t c) { + return (c >= 'a' && c <= 'z' && label->data[offset] == c - 32) || (c >= 'A' && c <= 'Z' && label->data[offset] == c + 32); +} + +mdns::Label * mdns::Label::Iterator::getStartLabel() { + return startLabel; +} + +mdns::Label * mdns::Label::Matcher::match(std::map labels, Buffer * buffer) { + + Iterator * iterators[labels.size()]; + + std::map::const_iterator i; + + uint8_t idx = 0; + + for (i = labels.begin(); i != labels.end(); ++i) { + iterators[idx++] = new Iterator(i->second); + } + + Reader * reader = new Reader(buffer); + + while (reader->hasNext()) { + uint8_t size = reader->next(); + + uint8_t idx = 0; + + for (uint8_t i = 0; i < labels.size(); i++) { + iterators[i]->match(size); + } + + while(idx < size && reader->hasNext()) { + uint8_t c = reader->next(); + + for (uint8_t i = 0; i < labels.size(); i++) { + iterators[i]->match(c); + } + + idx++; + } + } + + + buffer->reset(); + + Label * label = NULL; + + if (reader->endOfName()) { + uint8_t idx = 0; + + while (label == NULL && idx < labels.size()) { + if (iterators[idx]->matched()) { + label = iterators[idx]->getStartLabel(); + } + + idx++; + } + } + + for (uint8_t i = 0; i < labels.size(); i++) { + delete iterators[i]; + } + + delete reader; + + return label; +} + +void mdns::Label::matched(uint16_t type, uint16_t cls) { +} + +mdns::HostLabel::HostLabel(Record * aRecord, Record * nsecRecord, String name, Label * nextLabel, bool caseSensitive):Label(name, nextLabel, caseSensitive) { + this->aRecord = aRecord; + this->nsecRecord = nsecRecord; +} + +void mdns::HostLabel::matched(uint16_t type, uint16_t cls) { + switch(type) { + case A_TYPE: + case ANY_TYPE: + aRecord->setAnswerRecord(); + nsecRecord->setAdditionalRecord(); + break; + + default: + nsecRecord->setAnswerRecord(); + } +} + +mdns::ServiceLabel::ServiceLabel(Record * aRecord, String name, Label * nextLabel, bool caseSensitive):Label(name, nextLabel, caseSensitive) { + this->aRecord = aRecord; +} + +void mdns::ServiceLabel::addInstance(Record * ptrRecord, Record * srvRecord, Record * txtRecord) { + ptrRecords.push_back(ptrRecord); + srvRecords.push_back(srvRecord); + txtRecords.push_back(txtRecord); +} + +void mdns::ServiceLabel::matched(uint16_t type, uint16_t cls) { + switch(type) { + case PTR_TYPE: + case ANY_TYPE: + for (std::vector::const_iterator i = ptrRecords.begin(); i != ptrRecords.end(); ++i) { + (*i)->setAnswerRecord(); + } + for (std::vector::const_iterator i = srvRecords.begin(); i != srvRecords.end(); ++i) { + (*i)->setAdditionalRecord(); + } + for (std::vector::const_iterator i = txtRecords.begin(); i != txtRecords.end(); ++i) { + (*i)->setAdditionalRecord(); + } + aRecord->setAdditionalRecord(); + break; + } +} + +mdns::InstanceLabel::InstanceLabel(Record * srvRecord, Record * txtRecord, Record * nsecRecord, Record * aRecord, String name, Label * nextLabel, bool caseSensitive):Label(name, nextLabel, caseSensitive) { + this->srvRecord = srvRecord; + this->txtRecord = txtRecord; + this->nsecRecord = nsecRecord; + this->aRecord = aRecord; +} + +void mdns::InstanceLabel::matched(uint16_t type, uint16_t cls) { + switch(type) { + case SRV_TYPE: + srvRecord->setAnswerRecord(); + txtRecord->setAdditionalRecord(); + nsecRecord->setAdditionalRecord(); + aRecord->setAdditionalRecord(); + break; + + case TXT_TYPE: + txtRecord->setAnswerRecord(); + srvRecord->setAdditionalRecord(); + nsecRecord->setAdditionalRecord(); + aRecord->setAdditionalRecord(); + break; + + case ANY_TYPE: + srvRecord->setAnswerRecord(); + txtRecord->setAnswerRecord(); + nsecRecord->setAdditionalRecord(); + aRecord->setAdditionalRecord(); + break; + + default: + nsecRecord->setAnswerRecord(); + } +} + +mdns::MetaLabel::MetaLabel(String name, Label * nextLabel):Label(name, nextLabel) { + // Do nothing +} + +void mdns::MetaLabel::addService(Record * ptrRecord) { + records.push_back(ptrRecord); +} + +void mdns::MetaLabel::matched(uint16_t type, uint16_t cls) { + switch(type) { + case PTR_TYPE: + case ANY_TYPE: + for (std::vector::const_iterator i = this->records.begin(); i != this->records.end(); ++i) { + (*i)->setAnswerRecord(); + } + break; + } +} + diff --git a/lib/MDNS/src/Label.h b/lib/MDNS/src/Label.h new file mode 100644 index 0000000..1a0366c --- /dev/null +++ b/lib/MDNS/src/Label.h @@ -0,0 +1,149 @@ +#include "application.h" + +#ifndef _INCL_LABEL +#define _INCL_LABEL + +#include "Buffer.h" +#include "Record.h" +#include +#include + +#define DOT '.' + +#define END_OF_NAME 0x0 +#define LABEL_POINTER 0xc0 +#define MAX_LABEL_SIZE 63 +#define INVALID_OFFSET -1 + +#define UNKNOWN_NAME -1 +#define BUFFER_UNDERFLOW -2 + +namespace mdns { + + class Label { + private: + + class Iterator; + + public: + class Matcher { + public: + Label * match(std::map labels, Buffer * buffer); + }; + + Label(String name, Label * nextLabel = NULL, bool caseSensitive = false); + + uint8_t getSize(); + + uint8_t getWriteSize(); + + void write(Buffer * buffer); + + virtual void matched(uint16_t type, uint16_t cls); + + void reset(); + + private: + class Reader { + public: + Reader(Buffer * buffer); + + bool hasNext(); + + uint8_t next(); + + bool endOfName(); + private: + Buffer * buffer; + uint8_t c = 1; + }; + + class Iterator { + public: + Iterator(Label * label); + + bool match(uint8_t c); + + bool matched(); + + Label * getStartLabel(); + + private: + Label * startLabel; + Label * label; + uint8_t size; + uint8_t offset = 0; + bool matches = true; + + bool equalsIgnoreCase(uint8_t c); + }; + + uint8_t * EMPTY_DATA = { END_OF_NAME }; + uint8_t * data; + bool caseSensitive; + Label * nextLabel; + int16_t writeOffset = INVALID_OFFSET; + }; + + class HostLabel : public Label { + + public: + + HostLabel(Record * aRecord, Record * nsecRecord, String name, Label * nextLabel = NULL, bool caseSensitive = false); + + virtual void matched(uint16_t type, uint16_t cls); + + private: + Record * aRecord; + Record * nsecRecord; + }; + + class ServiceLabel : public Label { + + public: + + ServiceLabel(Record * aRecord, String name, Label * nextLabel = NULL, bool caseSensitive = false); + + void addInstance(Record * ptrRecord, Record * srvRecord, Record * txtRecord); + + virtual void matched(uint16_t type, uint16_t cls); + + private: + Record * aRecord; + std::vector ptrRecords; + std::vector srvRecords; + std::vector txtRecords; + }; + + class InstanceLabel : public Label { + + public: + + InstanceLabel(Record * srvRecord, Record * txtRecord, Record * nsecRecord, Record * aRecord, String name, Label * nextLabel = NULL, bool caseSensitive = false); + + virtual void matched(uint16_t type, uint16_t cls); + + private: + Record * srvRecord; + Record * txtRecord; + Record * nsecRecord; + Record * aRecord; + }; + + class MetaLabel : public Label { + + public: + + MetaLabel(String name, Label * nextLabel); + + void addService(Record * ptrRecord); + + virtual void matched(uint16_t type, uint16_t cls); + + private: + std::vector records; + }; + +} + +#endif diff --git a/lib/MDNS/src/MDNS.cpp b/lib/MDNS/src/MDNS.cpp new file mode 100644 index 0000000..1e73fc9 --- /dev/null +++ b/lib/MDNS/src/MDNS.cpp @@ -0,0 +1,282 @@ +#include "MDNS.h" + +bool mdns::MDNS::setHostname(String hostname) { + bool success = true; + String status = "Ok"; + + if (labels[HOSTNAME]) { + status = "Hostname already set"; + success = false; + } + + if (success && hostname.length() < MAX_LABEL_SIZE && isAlphaDigitHyphen(hostname)) { + aRecord = new ARecord(); + + HostNSECRecord * hostNSECRecord = new HostNSECRecord(); + + records.push_back(aRecord); + records.push_back(hostNSECRecord); + + Label * label = new HostLabel(aRecord, hostNSECRecord, hostname, LOCAL); + + labels[HOSTNAME] = label; + labels[META_SERVICE] = META; + + aRecord->setLabel(label); + hostNSECRecord->setLabel(label); + } else { + status = success? "Invalid hostname" : status; + success = false; + } + + return success; +} + +bool mdns::MDNS::addService(String protocol, String service, uint16_t port, String instance, std::vector subServices) { + bool success = true; + String status = "Ok"; + + if (!labels[HOSTNAME]) { + status = "Hostname not set"; + success = false; + } + + if (success && protocol.length() < MAX_LABEL_SIZE - 1 && service.length() < MAX_LABEL_SIZE - 1 && + instance.length() < MAX_LABEL_SIZE && isAlphaDigitHyphen(protocol) && isAlphaDigitHyphen(service) && isNetUnicode(instance)) { + + PTRRecord * ptrRecord = new PTRRecord(); + SRVRecord * srvRecord = new SRVRecord(); + txtRecord = new TXTRecord(); + InstanceNSECRecord * instanceNSECRecord = new InstanceNSECRecord(); + PTRRecord * enumerationRecord = new PTRRecord(true); + + records.push_back(ptrRecord); + records.push_back(srvRecord); + records.push_back(txtRecord); + records.push_back(instanceNSECRecord); + records.push_back(enumerationRecord); + + String serviceString = "_" + service + "._" + protocol; + + Label * protocolLabel = new Label("_" + protocol, LOCAL); + + if (labels[serviceString] == NULL) { + labels[serviceString] = new ServiceLabel(aRecord, "_" + service, protocolLabel); + } + + ((ServiceLabel *) labels[serviceString])->addInstance(ptrRecord, srvRecord, txtRecord); + + String instanceString = instance + "._" + service + "._" + protocol; + + labels[instanceString] = new InstanceLabel(srvRecord, txtRecord, instanceNSECRecord, aRecord, instance, labels[serviceString], true); + META->addService(enumerationRecord); + + for (std::vector::const_iterator i = subServices.begin(); i != subServices.end(); ++i) { + String subServiceString = "_" + *i + "._sub." + serviceString; + + if (labels[subServiceString] == NULL) { + labels[subServiceString] = new ServiceLabel(aRecord, "_" + *i, new Label("_sub", labels[serviceString])); + } + + PTRRecord * subPTRRecord = new PTRRecord(); + PTRRecord * enumerationSubPTRRecord = new PTRRecord(true); + + subPTRRecord->setLabel(labels[subServiceString]); + subPTRRecord->setTargetLabel(labels[instanceString]); + + enumerationSubPTRRecord->setLabel(META); + enumerationSubPTRRecord->setTargetLabel(labels[subServiceString]); + + records.push_back(subPTRRecord); + records.push_back(enumerationSubPTRRecord); + + ((ServiceLabel *) labels[subServiceString])->addInstance(subPTRRecord, srvRecord, txtRecord); + META->addService(enumerationSubPTRRecord); + } + + ptrRecord->setLabel(labels[serviceString]); + ptrRecord->setTargetLabel(labels[instanceString]); + srvRecord->setLabel(labels[instanceString]); + srvRecord->setPort(port); + srvRecord->setHostLabel(labels[HOSTNAME]); + txtRecord->setLabel(labels[instanceString]); + instanceNSECRecord->setLabel(labels[instanceString]); + enumerationRecord->setLabel(META); + enumerationRecord->setTargetLabel(labels[serviceString]); + } else { + status = success? "Invalid name" : status; + success = false; + } + + return success; +} + +void mdns::MDNS::addTXTEntry(String key, String value) { + txtRecord->addEntry(key, value); +} + +bool mdns::MDNS::begin(bool announce) { + // Wait for WiFi to connect + while (!WiFi.ready()) { + } + + udp->begin(MDNS_PORT); + udp->joinMulticast(MDNS_ADDRESS); + + // TODO: Probing + + if (announce) { + for (std::vector::const_iterator i = records.begin(); i != records.end(); ++i) { + (*i)->announceRecord(); + } + + writeResponses(); + } + + return true; +} + +bool mdns::MDNS::processQueries() { + uint16_t n = udp->parsePacket(); + + if (n > 0) { + Serial.println(" MDNS::processQueries(): buffer->read(udp);"); + buffer->read(udp); + Serial.println(" MDNS::processQueries(): udp->flush();"); + udp->flush(); + Serial.println(" MDNS::processQueries(): getResponses();"); + getResponses(); + Serial.println(" MDNS::processQueries(): buffer->clear();"); + buffer->clear(); + Serial.println(" MDNS::processQueries(): writeResponses();"); + writeResponses(); + Serial.println(" MDNS::processQueries(): returning"); + } + + return n > 0; +} + +void mdns::MDNS::getResponses() { + QueryHeader header = readHeader(buffer); + + if ((header.flags & 0x8000) == 0 && header.qdcount > 0) { + uint8_t count = 0; + + while (count++ < header.qdcount && buffer->available() > 0) { + Label * label = matcher->match(labels, buffer); + + if (buffer->available() >= 4) { + uint16_t type = buffer->readUInt16(); + uint16_t cls = buffer->readUInt16(); + + if (label != NULL) { + + label->matched(type, cls); + } + } else { + status = "Buffer underflow at index " + buffer->getOffset(); + } + } + } +} + +mdns::MDNS::QueryHeader mdns::MDNS::readHeader(Buffer * buffer) { + QueryHeader header; + + if (buffer->available() >= 12) { + header.id = buffer->readUInt16(); + header.flags = buffer->readUInt16(); + header.qdcount = buffer->readUInt16(); + header.ancount = buffer->readUInt16(); + header.nscount = buffer->readUInt16(); + header.arcount = buffer->readUInt16(); + } + + return header; +} + +void mdns::MDNS::writeResponses() { + + uint8_t answerCount = 0; + uint8_t additionalCount = 0; + + for (std::vector::const_iterator i = records.begin(); i != records.end(); ++i) { + if ((*i)->isAnswerRecord()) { + answerCount++; + } + if ((*i)->isAdditionalRecord()) { + additionalCount++; + } + } + + Serial.println(" MDNS::writeResponses(): [1]"); + if (answerCount > 0) { + buffer->writeUInt16(0x0); + buffer->writeUInt16(0x8400); + buffer->writeUInt16(0x0); + buffer->writeUInt16(answerCount); + buffer->writeUInt16(0x0); + buffer->writeUInt16(additionalCount); + Serial.println(" MDNS::writeResponses(): [2]"); + + for (std::vector::const_iterator i = records.begin(); i != records.end(); ++i) { + if ((*i)->isAnswerRecord()) { + (*i)->write(buffer); + } + } + Serial.println(" MDNS::writeResponses(): [3]"); + + for (std::vector::const_iterator i = records.begin(); i != records.end(); ++i) { + if ((*i)->isAdditionalRecord()) { + (*i)->write(buffer); + } + } + Serial.println(" MDNS::writeResponses(): [4]"); + } + Serial.println(" MDNS::writeResponses(): [5]"); + if (buffer->available() > 0) { + Serial.println(" MDNS::writeResponses(): [6]"); + udp->beginPacket(MDNS_ADDRESS, MDNS_PORT); + Serial.println(" MDNS::writeResponses(): [7]"); + buffer->write(udp); + Serial.println(" MDNS::writeResponses(): [8]"); + udp->endPacket(); + Serial.println(" MDNS::writeResponses(): [9]"); + } + Serial.println(" MDNS::writeResponses(): [10]"); + for (std::map::const_iterator i = labels.begin(); i != labels.end(); ++i) { + i->second->reset(); + } + Serial.println(" MDNS::writeResponses(): [11]"); + for (std::vector::const_iterator i = records.begin(); i != records.end(); ++i) { + (*i)->reset(); + } +} + +bool mdns::MDNS::isAlphaDigitHyphen(String string) { + bool result = true; + + uint8_t idx = 0; + + while (result && idx < string.length()) { + uint8_t c = string.charAt(idx++); + + result = (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '-'; + } + + return result; +} + +bool mdns::MDNS::isNetUnicode(String string) { + bool result = true; + + uint8_t idx = 0; + + while (result && idx < string.length()) { + uint8_t c = string.charAt(idx++); + + result = c >= 0x1f && c != 0x7f; + } + + return result; +} diff --git a/lib/MDNS/src/MDNS.h b/lib/MDNS/src/MDNS.h new file mode 100644 index 0000000..e0651bf --- /dev/null +++ b/lib/MDNS/src/MDNS.h @@ -0,0 +1,68 @@ +#include "application.h" + +#ifndef _INCL_MDNS +#define _INCL_MDNS + +#include "Buffer.h" +#include "Label.h" +#include "Record.h" +#include +#include + +#define MDNS_ADDRESS IPAddress(224, 0, 0, 251) +#define MDNS_PORT 5353 + +#define BUFFER_SIZE 512 +#define HOSTNAME "" +#define META_SERVICE "_services._dns-sd._udp" + +namespace mdns { + + class MDNS { + public: + + bool setHostname(String hostname); + + bool addService(String protocol, String service, uint16_t port, String instance, std::vector subServices = std::vector()); + + void addTXTEntry(String key, String value = ""); + + bool begin(bool announce = false); + + bool processQueries(); + + private: + + struct QueryHeader { + uint16_t id; + uint16_t flags; + uint16_t qdcount; + uint16_t ancount; + uint16_t nscount; + uint16_t arcount; + }; + + UDP * udp = new UDP(); + Buffer * buffer = new Buffer(BUFFER_SIZE); + + Label * ROOT = new Label(""); + Label * LOCAL = new Label("local", ROOT); + MetaLabel * META = new MetaLabel("_services", new Label("_dns-sd", new Label("_udp", LOCAL))); + Label::Matcher * matcher = new Label::Matcher(); + + ARecord * aRecord; + TXTRecord * txtRecord; + + std::map labels; + std::vector records; + String status = "Ok"; + + QueryHeader readHeader(Buffer * buffer); + void getResponses(); + void writeResponses(); + bool isAlphaDigitHyphen(String string); + bool isNetUnicode(String string); + }; + +} +#endif diff --git a/lib/MDNS/src/Record.cpp b/lib/MDNS/src/Record.cpp new file mode 100644 index 0000000..0d7c310 --- /dev/null +++ b/lib/MDNS/src/Record.cpp @@ -0,0 +1,165 @@ +#include "Record.h" + +#include "Label.h" + +mdns::Record::Record(uint16_t type, uint16_t cls, uint32_t ttl, bool announce) { + this->type = type; + this->cls = cls; + this->ttl = ttl; + this->announce = announce; +} + +void mdns::Record::setLabel(Label * label) { + this->label = label; +} + +void mdns::Record::announceRecord() { + if (this->announce) { + this->answerRecord = true; + } +} + +void mdns::Record::setAnswerRecord() { + this->answerRecord = true; +} + +bool mdns::Record::isAnswerRecord() { + return answerRecord && !knownRecord; +} + +void mdns::Record::setAdditionalRecord() { + this->additionalRecord = true; +} + +bool mdns::Record::isAdditionalRecord() { + return additionalRecord && !answerRecord && !knownRecord; +} + +void mdns::Record::setKnownRecord() { + this->knownRecord = true; +} + +void mdns::Record::write(Buffer * buffer) { + label->write(buffer); + buffer->writeUInt16(type); + buffer->writeUInt16(cls); + buffer->writeUInt32(ttl); + writeSpecific(buffer); +} + +void mdns::Record::reset() { + this->answerRecord = false; + this->additionalRecord = false; + this->knownRecord = false; +} + +mdns::Label * mdns::Record::getLabel() { + return label; +} + +mdns::ARecord::ARecord():Record(A_TYPE, IN_CLASS | CACHE_FLUSH, TTL_2MIN) { +} + +void mdns::ARecord::writeSpecific(Buffer * buffer) { + buffer->writeUInt16(4); + IPAddress ip = WiFi.localIP(); + for (int i = 0; i < IP_SIZE; i++) { + buffer->writeUInt8(ip[i]); + } +} + +mdns::NSECRecord::NSECRecord():Record(NSEC_TYPE, IN_CLASS | CACHE_FLUSH, TTL_2MIN) { +} + +mdns::HostNSECRecord::HostNSECRecord():NSECRecord() { +} + +void mdns::HostNSECRecord::writeSpecific(Buffer * buffer) { + buffer->writeUInt16(5); + getLabel()->write(buffer); + buffer->writeUInt8(0); + buffer->writeUInt8(1); + buffer->writeUInt8(0x40); +} + +mdns::InstanceNSECRecord::InstanceNSECRecord():NSECRecord() { +} + +void mdns::InstanceNSECRecord::writeSpecific(Buffer * buffer) { + buffer->writeUInt16(9); + getLabel()->write(buffer); + buffer->writeUInt8(0); + buffer->writeUInt8(5); + buffer->writeUInt8(0); + buffer->writeUInt8(0); + buffer->writeUInt8(0x80); + buffer->writeUInt8(0); + buffer->writeUInt8(0x40); +} + +mdns::PTRRecord::PTRRecord(bool meta):Record(PTR_TYPE, IN_CLASS, TTL_75MIN, !meta) { +} + +void mdns::PTRRecord::writeSpecific(Buffer * buffer) { + buffer->writeUInt16(targetLabel->getWriteSize()); + targetLabel->write(buffer); +} + +void mdns::PTRRecord::setTargetLabel(Label * label) { + targetLabel = label; +} + +mdns::SRVRecord::SRVRecord():Record(SRV_TYPE, IN_CLASS | CACHE_FLUSH, TTL_2MIN) { +} + +void mdns::SRVRecord::writeSpecific(Buffer * buffer) { + buffer->writeUInt16(6 + hostLabel->getWriteSize()); + buffer->writeUInt16(0); + buffer->writeUInt16(0); + buffer->writeUInt16(port); + hostLabel->write(buffer); +} + +void mdns::SRVRecord::setHostLabel(Label * label) { + hostLabel = label; +} + +void mdns::SRVRecord::setPort(uint16_t port) { + this->port = port; +} + +mdns::TXTRecord::TXTRecord():Record(TXT_TYPE, IN_CLASS | CACHE_FLUSH, TTL_75MIN) { +} + +void mdns::TXTRecord::addEntry(String key, String value) { + String entry = key; + + if (value == NULL || value.length() > 0) { + entry += '='; + entry += value; + } + + data.push_back(entry); +} + +void mdns::TXTRecord::writeSpecific(Buffer * buffer) { + uint16_t size = 0; + + std::vector::const_iterator i; + + for(i = data.begin(); i != data.end(); ++i) { + size += i->length() + 1; + } + + buffer->writeUInt16(size); + + for(i = data.begin(); i != data.end(); ++i) { + uint8_t length = i->length(); + + buffer->writeUInt8(length); + + for (uint8_t idx = 0; idx < length; idx++) { + buffer->writeUInt8(i->charAt(idx)); + } + } +} diff --git a/lib/MDNS/src/Record.h b/lib/MDNS/src/Record.h new file mode 100644 index 0000000..8ad424c --- /dev/null +++ b/lib/MDNS/src/Record.h @@ -0,0 +1,157 @@ +#include "application.h" + +#ifndef _INCL_RECORD +#define _INCL_RECORD + +#include "Buffer.h" +#include + +#define IN_CLASS 1 +#define CACHE_FLUSH 0x8000 + +#define A_TYPE 0x01 +#define PTR_TYPE 0x0c +#define TXT_TYPE 0x10 +#define AAAA_TYPE 0x1c +#define SRV_TYPE 0x21 +#define NSEC_TYPE 0x2f + +#define ANY_TYPE 0xFF + +#define TTL_2MIN 120 +#define TTL_75MIN 4500 + +#define IP_SIZE 4 + +namespace mdns { + class Label; + + class Record { + + public: + + void setLabel(Label * label); + + void announceRecord(); + + void setAnswerRecord(); + + bool isAnswerRecord(); + + void setAdditionalRecord(); + + bool isAdditionalRecord(); + + void setKnownRecord(); + + void write(Buffer * buffer); + + void reset(); + + protected: + + Record(uint16_t type, uint16_t cls, uint32_t ttl, bool announce = true); + + Label * getLabel(); + + virtual void writeSpecific(Buffer * buffer) = 0; + + private: + + Label * label; + uint16_t type; + uint16_t cls; + uint32_t ttl; + bool announce; + bool answerRecord = false; + bool additionalRecord = false; + bool knownRecord = false; + }; + + class ARecord : public Record { + + public: + + ARecord(); + + virtual void writeSpecific(Buffer * buffer); + }; + + class NSECRecord : public Record { + + public: + + NSECRecord(); + + virtual void writeSpecific(Buffer * buffer) = 0; + }; + + class HostNSECRecord : public NSECRecord { + + public: + + HostNSECRecord(); + + virtual void writeSpecific(Buffer * buffer); + }; + + class InstanceNSECRecord : public NSECRecord { + + public: + + InstanceNSECRecord(); + + virtual void writeSpecific(Buffer * buffer); + }; + + class PTRRecord : public Record { + + public: + + PTRRecord(bool meta = false); + + virtual void writeSpecific(Buffer * buffer); + + void setTargetLabel(Label * label); + + private: + + Label * targetLabel; + + }; + + class SRVRecord : public Record { + + public: + + SRVRecord(); + + virtual void writeSpecific(Buffer * buffer); + + void setHostLabel(Label * label); + + void setPort(uint16_t port); + + private: + + Label * hostLabel; + uint16_t port; + }; + + class TXTRecord : public Record { + + public: + + TXTRecord(); + + virtual void writeSpecific(Buffer * buffer); + + void addEntry(String key, String value = ""); + + private: + + std::vector data; + }; +} + +#endif diff --git a/library.properties b/library.properties index c59c218..7bcaab7 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=hackerpet_plus_dev -version=0.1.53 +version=0.1.64 license=AGPL author=Csaba Petre maintainer=Csaba Petre @@ -9,4 +9,3 @@ url=http://hackerpet.com repository=https://github.com/CleverPet/hackerpet_plus/ architectures=particle-photon dependencies.hackerpet=0.2.6 -dependencies.MDNS=2.0.0 \ No newline at end of file diff --git a/project.properties b/project.properties index 62c9ae3..682c7f3 100644 --- a/project.properties +++ b/project.properties @@ -1,3 +1,2 @@ name=hackerpet_plus dependencies.hackerpet=0.2.6 -dependencies.MDNS=2.0.0 diff --git a/src/config-manager.cpp b/src/config-manager.cpp index 5ca76c3..9b06b68 100644 --- a/src/config-manager.cpp +++ b/src/config-manager.cpp @@ -5,7 +5,7 @@ using namespace std; -#include +#include "../lib/MDNS/src/MDNS.h" using namespace mdns; diff --git a/src/config-manager.h b/src/config-manager.h index 3c670a9..e49575b 100644 --- a/src/config-manager.h +++ b/src/config-manager.h @@ -2,7 +2,7 @@ #define CONFIG_MANAGER_H #include "Particle.h" -#include +#include "../lib/MDNS/src/MDNS.h" using namespace mdns; #include "http-server-util.h" diff --git a/src/http-server-util.cpp b/src/http-server-util.cpp index db76510..6b2b16c 100644 --- a/src/http-server-util.cpp +++ b/src/http-server-util.cpp @@ -1,4 +1,5 @@ -#include +#include "../lib/MDNS/src/MDNS.h" + using namespace mdns; #include "http-server-util.h" diff --git a/src/http-server-util.h b/src/http-server-util.h index 1dc1fb1..88941b2 100644 --- a/src/http-server-util.h +++ b/src/http-server-util.h @@ -3,7 +3,7 @@ #include -#include +#include "../lib/MDNS/src/MDNS.h" using namespace mdns; using namespace std; From dc4263b8240066f311be34a94521082475199bfd Mon Sep 17 00:00:00 2001 From: asingularity Date: Tue, 20 Sep 2022 18:51:06 -0700 Subject: [PATCH 06/14] more debugging for getResponses which is where freeze seems to occur... --- lib/MDNS/src/MDNS.cpp | 18 ++++++++++++++---- library.properties | 2 +- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/lib/MDNS/src/MDNS.cpp b/lib/MDNS/src/MDNS.cpp index 1e73fc9..e49d8f6 100644 --- a/lib/MDNS/src/MDNS.cpp +++ b/lib/MDNS/src/MDNS.cpp @@ -157,27 +157,37 @@ bool mdns::MDNS::processQueries() { } void mdns::MDNS::getResponses() { + Serial.println(" MDNS::getResponses(): [1]"); QueryHeader header = readHeader(buffer); - + Serial.println(" MDNS::getResponses(): [2]"); if ((header.flags & 0x8000) == 0 && header.qdcount > 0) { uint8_t count = 0; - + Serial.println(" MDNS::getResponses(): [3]"); while (count++ < header.qdcount && buffer->available() > 0) { + Serial.println(" MDNS::getResponses(): [4]"); Label * label = matcher->match(labels, buffer); - + Serial.println(" MDNS::getResponses(): [5]"); if (buffer->available() >= 4) { + Serial.println(" MDNS::getResponses(): [6]"); uint16_t type = buffer->readUInt16(); + Serial.println(" MDNS::getResponses(): [7]"); uint16_t cls = buffer->readUInt16(); + Serial.println(" MDNS::getResponses(): [8]"); if (label != NULL) { - + Serial.println(" MDNS::getResponses(): [9]"); label->matched(type, cls); + Serial.println(" MDNS::getResponses(): [10]"); } } else { + Serial.println(" MDNS::getResponses(): [11]"); status = "Buffer underflow at index " + buffer->getOffset(); } + Serial.println(" MDNS::getResponses(): [12]"); } + Serial.println(" MDNS::getResponses(): [13]"); } + Serial.println(" MDNS::getResponses(): [14]"); } mdns::MDNS::QueryHeader mdns::MDNS::readHeader(Buffer * buffer) { diff --git a/library.properties b/library.properties index 7bcaab7..98364ea 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=hackerpet_plus_dev -version=0.1.64 +version=0.1.65 license=AGPL author=Csaba Petre maintainer=Csaba Petre From 30740dd8c649e5f6f3b8d40bc83202a4821edb28 Mon Sep 17 00:00:00 2001 From: asingularity Date: Sat, 24 Sep 2022 14:22:41 -0700 Subject: [PATCH 07/14] more debugging: identified bug! mdns::Label::Reader::next infinite loop! --- lib/MDNS/src/Label.cpp | 54 ++++++++++++++++++++++++++---------------- library.properties | 2 +- 2 files changed, 34 insertions(+), 22 deletions(-) diff --git a/lib/MDNS/src/Label.cpp b/lib/MDNS/src/Label.cpp index ca8babe..dfd6c46 100644 --- a/lib/MDNS/src/Label.cpp +++ b/lib/MDNS/src/Label.cpp @@ -77,22 +77,27 @@ bool mdns::Label::Reader::hasNext() { } uint8_t mdns::Label::Reader::next() { + Serial.println(" mdns::Label::Reader::next: [1]"); c = buffer->readUInt8(); - + Serial.println(" mdns::Label::Reader::next: [2]"); while ((c & LABEL_POINTER) == LABEL_POINTER) { + Serial.println(" mdns::Label::Reader::next: [3]"); if (buffer->available() > 0) { + Serial.println(" mdns::Label::Reader::next: [4]"); uint8_t c2 = buffer->readUInt8(); - + Serial.println(" mdns::Label::Reader::next: [5]"); uint16_t pointerOffset = ((c & ~LABEL_POINTER) << 8) | c2; - + Serial.println(" mdns::Label::Reader::next: [6]"); buffer->mark(); - + Serial.println(" mdns::Label::Reader::next: [7]"); buffer->setOffset(pointerOffset); - + Serial.println(" mdns::Label::Reader::next: [8]"); c = buffer->readUInt8(); + Serial.println(" mdns::Label::Reader::next: [9]"); } + Serial.println(" mdns::Label::Reader::next: [10]"); } - + Serial.println(" mdns::Label::Reader::next: [11]"); return c; } @@ -136,61 +141,68 @@ mdns::Label * mdns::Label::Iterator::getStartLabel() { mdns::Label * mdns::Label::Matcher::match(std::map labels, Buffer * buffer) { + Serial.println(" mdns::Label::Matcher::match: [1]"); Iterator * iterators[labels.size()]; - + Serial.println(" mdns::Label::Matcher::match: [2]"); std::map::const_iterator i; uint8_t idx = 0; - + Serial.println(" mdns::Label::Matcher::match: [3]"); for (i = labels.begin(); i != labels.end(); ++i) { iterators[idx++] = new Iterator(i->second); } + Serial.println(" mdns::Label::Matcher::match: [4]"); Reader * reader = new Reader(buffer); - + Serial.println(" mdns::Label::Matcher::match: [5]"); while (reader->hasNext()) { + Serial.println(" mdns::Label::Matcher::match: [6]"); uint8_t size = reader->next(); uint8_t idx = 0; - + Serial.println(" mdns::Label::Matcher::match: [7]"); for (uint8_t i = 0; i < labels.size(); i++) { iterators[i]->match(size); } - + Serial.println(" mdns::Label::Matcher::match: [8]"); while(idx < size && reader->hasNext()) { + Serial.println(" mdns::Label::Matcher::match: [8.1]"); uint8_t c = reader->next(); - + Serial.println(" mdns::Label::Matcher::match: [8.2]"); for (uint8_t i = 0; i < labels.size(); i++) { + Serial.println(" mdns::Label::Matcher::match: [8.3]"); iterators[i]->match(c); } - + Serial.println(" mdns::Label::Matcher::match: [8.4]"); idx++; } + Serial.println(" mdns::Label::Matcher::match: [9]"); } - + Serial.println(" mdns::Label::Matcher::match: [10]"); buffer->reset(); - + Serial.println(" mdns::Label::Matcher::match: [11]"); Label * label = NULL; - + Serial.println(" mdns::Label::Matcher::match: [12]"); if (reader->endOfName()) { uint8_t idx = 0; - + Serial.println(" mdns::Label::Matcher::match: [13]"); while (label == NULL && idx < labels.size()) { + Serial.println(" mdns::Label::Matcher::match: [14]"); if (iterators[idx]->matched()) { label = iterators[idx]->getStartLabel(); } - + Serial.println(" mdns::Label::Matcher::match: [15]"); idx++; } } - + Serial.println(" mdns::Label::Matcher::match: [16]"); for (uint8_t i = 0; i < labels.size(); i++) { delete iterators[i]; } - + Serial.println(" mdns::Label::Matcher::match: [17]"); delete reader; - + Serial.println(" mdns::Label::Matcher::match: [18]"); return label; } diff --git a/library.properties b/library.properties index 98364ea..8ef4483 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=hackerpet_plus_dev -version=0.1.65 +version=0.1.67 license=AGPL author=Csaba Petre maintainer=Csaba Petre From df065aa0bafa29fdcb1d5f19ba45fbd9d15a0094 Mon Sep 17 00:00:00 2001 From: asingularity Date: Mon, 26 Sep 2022 14:05:29 -0700 Subject: [PATCH 08/14] version that fixes the problem, testing in progress --- lib/MDNS/src/Label.cpp | 69 +++++++++++++++++++++++------------------- lib/MDNS/src/MDNS.cpp | 48 ++++++++++++++--------------- library.properties | 2 +- 3 files changed, 63 insertions(+), 56 deletions(-) diff --git a/lib/MDNS/src/Label.cpp b/lib/MDNS/src/Label.cpp index dfd6c46..2c3c3e3 100644 --- a/lib/MDNS/src/Label.cpp +++ b/lib/MDNS/src/Label.cpp @@ -79,23 +79,30 @@ bool mdns::Label::Reader::hasNext() { uint8_t mdns::Label::Reader::next() { Serial.println(" mdns::Label::Reader::next: [1]"); c = buffer->readUInt8(); - Serial.println(" mdns::Label::Reader::next: [2]"); + //Serial.println(" mdns::Label::Reader::next: [2]"); while ((c & LABEL_POINTER) == LABEL_POINTER) { - Serial.println(" mdns::Label::Reader::next: [3]"); + //Serial.println(" mdns::Label::Reader::next: [3]"); + if (buffer->available() > 0) { - Serial.println(" mdns::Label::Reader::next: [4]"); + //Serial.println(" mdns::Label::Reader::next: [4]"); uint8_t c2 = buffer->readUInt8(); - Serial.println(" mdns::Label::Reader::next: [5]"); + //Serial.println(" mdns::Label::Reader::next: [5]"); uint16_t pointerOffset = ((c & ~LABEL_POINTER) << 8) | c2; - Serial.println(" mdns::Label::Reader::next: [6]"); + //Serial.println(" mdns::Label::Reader::next: [6]"); buffer->mark(); - Serial.println(" mdns::Label::Reader::next: [7]"); + //Serial.println(" mdns::Label::Reader::next: [7]"); buffer->setOffset(pointerOffset); - Serial.println(" mdns::Label::Reader::next: [8]"); + //Serial.println(" mdns::Label::Reader::next: [8]"); c = buffer->readUInt8(); - Serial.println(" mdns::Label::Reader::next: [9]"); + //Serial.println(" mdns::Label::Reader::next: [9]"); + } + else + { + Serial.println("mdns::Label::Reader::next():: AVOIDING INFINITE LOOP, RETURNING!"); + return c; } - Serial.println(" mdns::Label::Reader::next: [10]"); + + //Serial.println(" mdns::Label::Reader::next: [10]"); } Serial.println(" mdns::Label::Reader::next: [11]"); return c; @@ -141,68 +148,68 @@ mdns::Label * mdns::Label::Iterator::getStartLabel() { mdns::Label * mdns::Label::Matcher::match(std::map labels, Buffer * buffer) { - Serial.println(" mdns::Label::Matcher::match: [1]"); + //Serial.println(" mdns::Label::Matcher::match: [1]"); Iterator * iterators[labels.size()]; - Serial.println(" mdns::Label::Matcher::match: [2]"); + //Serial.println(" mdns::Label::Matcher::match: [2]"); std::map::const_iterator i; uint8_t idx = 0; - Serial.println(" mdns::Label::Matcher::match: [3]"); + //Serial.println(" mdns::Label::Matcher::match: [3]"); for (i = labels.begin(); i != labels.end(); ++i) { iterators[idx++] = new Iterator(i->second); } - Serial.println(" mdns::Label::Matcher::match: [4]"); + //Serial.println(" mdns::Label::Matcher::match: [4]"); Reader * reader = new Reader(buffer); - Serial.println(" mdns::Label::Matcher::match: [5]"); + //Serial.println(" mdns::Label::Matcher::match: [5]"); while (reader->hasNext()) { - Serial.println(" mdns::Label::Matcher::match: [6]"); + // Serial.println(" mdns::Label::Matcher::match: [6]"); uint8_t size = reader->next(); uint8_t idx = 0; - Serial.println(" mdns::Label::Matcher::match: [7]"); + // Serial.println(" mdns::Label::Matcher::match: [7]"); for (uint8_t i = 0; i < labels.size(); i++) { iterators[i]->match(size); } - Serial.println(" mdns::Label::Matcher::match: [8]"); + // Serial.println(" mdns::Label::Matcher::match: [8]"); while(idx < size && reader->hasNext()) { - Serial.println(" mdns::Label::Matcher::match: [8.1]"); + // Serial.println(" mdns::Label::Matcher::match: [8.1]"); uint8_t c = reader->next(); - Serial.println(" mdns::Label::Matcher::match: [8.2]"); + // Serial.println(" mdns::Label::Matcher::match: [8.2]"); for (uint8_t i = 0; i < labels.size(); i++) { - Serial.println(" mdns::Label::Matcher::match: [8.3]"); + // Serial.println(" mdns::Label::Matcher::match: [8.3]"); iterators[i]->match(c); } - Serial.println(" mdns::Label::Matcher::match: [8.4]"); + // Serial.println(" mdns::Label::Matcher::match: [8.4]"); idx++; } - Serial.println(" mdns::Label::Matcher::match: [9]"); + // Serial.println(" mdns::Label::Matcher::match: [9]"); } - Serial.println(" mdns::Label::Matcher::match: [10]"); + // Serial.println(" mdns::Label::Matcher::match: [10]"); buffer->reset(); - Serial.println(" mdns::Label::Matcher::match: [11]"); + // Serial.println(" mdns::Label::Matcher::match: [11]"); Label * label = NULL; - Serial.println(" mdns::Label::Matcher::match: [12]"); + // Serial.println(" mdns::Label::Matcher::match: [12]"); if (reader->endOfName()) { uint8_t idx = 0; - Serial.println(" mdns::Label::Matcher::match: [13]"); + // Serial.println(" mdns::Label::Matcher::match: [13]"); while (label == NULL && idx < labels.size()) { - Serial.println(" mdns::Label::Matcher::match: [14]"); + // Serial.println(" mdns::Label::Matcher::match: [14]"); if (iterators[idx]->matched()) { label = iterators[idx]->getStartLabel(); } - Serial.println(" mdns::Label::Matcher::match: [15]"); + // Serial.println(" mdns::Label::Matcher::match: [15]"); idx++; } } - Serial.println(" mdns::Label::Matcher::match: [16]"); +// Serial.println(" mdns::Label::Matcher::match: [16]"); for (uint8_t i = 0; i < labels.size(); i++) { delete iterators[i]; } - Serial.println(" mdns::Label::Matcher::match: [17]"); +// Serial.println(" mdns::Label::Matcher::match: [17]"); delete reader; - Serial.println(" mdns::Label::Matcher::match: [18]"); + // Serial.println(" mdns::Label::Matcher::match: [18]"); return label; } diff --git a/lib/MDNS/src/MDNS.cpp b/lib/MDNS/src/MDNS.cpp index e49d8f6..98d10af 100644 --- a/lib/MDNS/src/MDNS.cpp +++ b/lib/MDNS/src/MDNS.cpp @@ -157,37 +157,37 @@ bool mdns::MDNS::processQueries() { } void mdns::MDNS::getResponses() { - Serial.println(" MDNS::getResponses(): [1]"); + // Serial.println(" MDNS::getResponses(): [1]"); QueryHeader header = readHeader(buffer); - Serial.println(" MDNS::getResponses(): [2]"); + // Serial.println(" MDNS::getResponses(): [2]"); if ((header.flags & 0x8000) == 0 && header.qdcount > 0) { uint8_t count = 0; - Serial.println(" MDNS::getResponses(): [3]"); + // Serial.println(" MDNS::getResponses(): [3]"); while (count++ < header.qdcount && buffer->available() > 0) { Serial.println(" MDNS::getResponses(): [4]"); Label * label = matcher->match(labels, buffer); - Serial.println(" MDNS::getResponses(): [5]"); + // Serial.println(" MDNS::getResponses(): [5]"); if (buffer->available() >= 4) { - Serial.println(" MDNS::getResponses(): [6]"); + // Serial.println(" MDNS::getResponses(): [6]"); uint16_t type = buffer->readUInt16(); - Serial.println(" MDNS::getResponses(): [7]"); + // Serial.println(" MDNS::getResponses(): [7]"); uint16_t cls = buffer->readUInt16(); - Serial.println(" MDNS::getResponses(): [8]"); + // Serial.println(" MDNS::getResponses(): [8]"); if (label != NULL) { - Serial.println(" MDNS::getResponses(): [9]"); + // Serial.println(" MDNS::getResponses(): [9]"); label->matched(type, cls); - Serial.println(" MDNS::getResponses(): [10]"); + // Serial.println(" MDNS::getResponses(): [10]"); } } else { - Serial.println(" MDNS::getResponses(): [11]"); + // Serial.println(" MDNS::getResponses(): [11]"); status = "Buffer underflow at index " + buffer->getOffset(); } - Serial.println(" MDNS::getResponses(): [12]"); + // Serial.println(" MDNS::getResponses(): [12]"); } - Serial.println(" MDNS::getResponses(): [13]"); + // Serial.println(" MDNS::getResponses(): [13]"); } - Serial.println(" MDNS::getResponses(): [14]"); + // Serial.println(" MDNS::getResponses(): [14]"); } mdns::MDNS::QueryHeader mdns::MDNS::readHeader(Buffer * buffer) { @@ -219,7 +219,7 @@ void mdns::MDNS::writeResponses() { } } - Serial.println(" MDNS::writeResponses(): [1]"); + // Serial.println(" MDNS::writeResponses(): [1]"); if (answerCount > 0) { buffer->writeUInt16(0x0); buffer->writeUInt16(0x8400); @@ -227,37 +227,37 @@ void mdns::MDNS::writeResponses() { buffer->writeUInt16(answerCount); buffer->writeUInt16(0x0); buffer->writeUInt16(additionalCount); - Serial.println(" MDNS::writeResponses(): [2]"); + // Serial.println(" MDNS::writeResponses(): [2]"); for (std::vector::const_iterator i = records.begin(); i != records.end(); ++i) { if ((*i)->isAnswerRecord()) { (*i)->write(buffer); } } - Serial.println(" MDNS::writeResponses(): [3]"); + // Serial.println(" MDNS::writeResponses(): [3]"); for (std::vector::const_iterator i = records.begin(); i != records.end(); ++i) { if ((*i)->isAdditionalRecord()) { (*i)->write(buffer); } } - Serial.println(" MDNS::writeResponses(): [4]"); + // Serial.println(" MDNS::writeResponses(): [4]"); } - Serial.println(" MDNS::writeResponses(): [5]"); + // Serial.println(" MDNS::writeResponses(): [5]"); if (buffer->available() > 0) { - Serial.println(" MDNS::writeResponses(): [6]"); + // Serial.println(" MDNS::writeResponses(): [6]"); udp->beginPacket(MDNS_ADDRESS, MDNS_PORT); - Serial.println(" MDNS::writeResponses(): [7]"); + // Serial.println(" MDNS::writeResponses(): [7]"); buffer->write(udp); - Serial.println(" MDNS::writeResponses(): [8]"); + // Serial.println(" MDNS::writeResponses(): [8]"); udp->endPacket(); - Serial.println(" MDNS::writeResponses(): [9]"); + // Serial.println(" MDNS::writeResponses(): [9]"); } - Serial.println(" MDNS::writeResponses(): [10]"); + // Serial.println(" MDNS::writeResponses(): [10]"); for (std::map::const_iterator i = labels.begin(); i != labels.end(); ++i) { i->second->reset(); } - Serial.println(" MDNS::writeResponses(): [11]"); + // Serial.println(" MDNS::writeResponses(): [11]"); for (std::vector::const_iterator i = records.begin(); i != records.end(); ++i) { (*i)->reset(); } diff --git a/library.properties b/library.properties index 8ef4483..5bfa93c 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=hackerpet_plus_dev -version=0.1.67 +version=0.1.69 license=AGPL author=Csaba Petre maintainer=Csaba Petre From a85b0d2f5c5571fbe1cef1136279dbea64b2f453 Mon Sep 17 00:00:00 2001 From: asingularity Date: Mon, 26 Sep 2022 14:50:58 -0700 Subject: [PATCH 09/14] comment logging; run functions on every loop --- examples/main/particle-test-local.ino | 35 ++++++++++++++------------- lib/MDNS/src/Label.cpp | 4 +-- lib/MDNS/src/MDNS.cpp | 14 +++++------ library.properties | 2 +- src/config-manager.cpp | 18 +++++++------- src/game-manager.cpp | 4 +-- 6 files changed, 39 insertions(+), 38 deletions(-) diff --git a/examples/main/particle-test-local.ino b/examples/main/particle-test-local.ino index 5587985..517251b 100644 --- a/examples/main/particle-test-local.ino +++ b/examples/main/particle-test-local.ino @@ -50,23 +50,24 @@ unsigned long FREE_MEMORY; // loop() runs over and over again, as quickly as it can execute. void loop() { - if ((millis() - lastmemcheck) > 1000) { - // serve webpage, read/write eeprom as config changes - Serial.println("[[calling]]: configMan.Run();"); - configMan.Run(); - - // ************************************ DISABLE FOR TESTING WITHOUT HUB ************************************ - // run the hub - Serial.println("[[calling]]: hub.Run(20);"); - hub.Run(20); - // ************************************ ************************************ ************************************ - - // run the loop for the current active game - Serial.println("[[calling]]: gameMan.Run();"); - gameMan.Run(); - - Serial.print(Time.timeStr()); - Serial.println("[[calling]]: free memory"); + + // serve webpage, read/write eeprom as config changes + // Serial.println("[[calling]]: configMan.Run();"); + configMan.Run(); + + // ************************************ DISABLE FOR TESTING WITHOUT HUB ************************************ + // run the hub + // Serial.println("[[calling]]: hub.Run(20);"); + hub.Run(20); + // ************************************ ************************************ ************************************ + + // run the loop for the current active game + // Serial.println("[[calling]]: gameMan.Run();"); + gameMan.Run(); + + if ((millis() - lastmemcheck) > 1000) { + // Serial.print(Time.timeStr()); + // Serial.println("[[calling]]: free memory"); FREE_MEMORY = System.freeMemory(); diff --git a/lib/MDNS/src/Label.cpp b/lib/MDNS/src/Label.cpp index 2c3c3e3..6fa7639 100644 --- a/lib/MDNS/src/Label.cpp +++ b/lib/MDNS/src/Label.cpp @@ -77,7 +77,7 @@ bool mdns::Label::Reader::hasNext() { } uint8_t mdns::Label::Reader::next() { - Serial.println(" mdns::Label::Reader::next: [1]"); + //Serial.println(" mdns::Label::Reader::next: [1]"); c = buffer->readUInt8(); //Serial.println(" mdns::Label::Reader::next: [2]"); while ((c & LABEL_POINTER) == LABEL_POINTER) { @@ -104,7 +104,7 @@ uint8_t mdns::Label::Reader::next() { //Serial.println(" mdns::Label::Reader::next: [10]"); } - Serial.println(" mdns::Label::Reader::next: [11]"); + //Serial.println(" mdns::Label::Reader::next: [11]"); return c; } diff --git a/lib/MDNS/src/MDNS.cpp b/lib/MDNS/src/MDNS.cpp index 98d10af..3423c80 100644 --- a/lib/MDNS/src/MDNS.cpp +++ b/lib/MDNS/src/MDNS.cpp @@ -140,17 +140,17 @@ bool mdns::MDNS::processQueries() { uint16_t n = udp->parsePacket(); if (n > 0) { - Serial.println(" MDNS::processQueries(): buffer->read(udp);"); + //Serial.println(" MDNS::processQueries(): buffer->read(udp);"); buffer->read(udp); - Serial.println(" MDNS::processQueries(): udp->flush();"); + //Serial.println(" MDNS::processQueries(): udp->flush();"); udp->flush(); - Serial.println(" MDNS::processQueries(): getResponses();"); + //Serial.println(" MDNS::processQueries(): getResponses();"); getResponses(); - Serial.println(" MDNS::processQueries(): buffer->clear();"); + //Serial.println(" MDNS::processQueries(): buffer->clear();"); buffer->clear(); - Serial.println(" MDNS::processQueries(): writeResponses();"); + //Serial.println(" MDNS::processQueries(): writeResponses();"); writeResponses(); - Serial.println(" MDNS::processQueries(): returning"); + //Serial.println(" MDNS::processQueries(): returning"); } return n > 0; @@ -164,7 +164,7 @@ void mdns::MDNS::getResponses() { uint8_t count = 0; // Serial.println(" MDNS::getResponses(): [3]"); while (count++ < header.qdcount && buffer->available() > 0) { - Serial.println(" MDNS::getResponses(): [4]"); + //Serial.println(" MDNS::getResponses(): [4]"); Label * label = matcher->match(labels, buffer); // Serial.println(" MDNS::getResponses(): [5]"); if (buffer->available() >= 4) { diff --git a/library.properties b/library.properties index 5bfa93c..902c852 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=hackerpet_plus_dev -version=0.1.69 +version=0.1.70 license=AGPL author=Csaba Petre maintainer=Csaba Petre diff --git a/src/config-manager.cpp b/src/config-manager.cpp index 9b06b68..737865c 100644 --- a/src/config-manager.cpp +++ b/src/config-manager.cpp @@ -185,13 +185,13 @@ bool ConfigManager::Run() { if ((millis() - _last_mdns_loop_time)>1000) { - Serial.println(" >>>>>>>> Calling mgschwan_MDNS_loop ... >>>>>>>>"); + //Serial.println(" >>>>>>>> Calling mgschwan_MDNS_loop ... >>>>>>>>"); mgschwan_MDNS_loop(mgschwan_mdns); - Serial.println(" >>>>>>>> Done calling mgschwan_MDNS_loop. >>>>>>>>"); + //Serial.println(" >>>>>>>> Done calling mgschwan_MDNS_loop. >>>>>>>>"); _last_mdns_loop_time = millis(); } - Serial.println(" [[ConfigManager::Run()]]: 1!"); + //Serial.println(" [[ConfigManager::Run()]]: 1!"); _display_error_msg = "Your hub is working."; if (_hub->IsHubOutOfFood()) { @@ -210,15 +210,15 @@ bool ConfigManager::Run() _display_error_msg = "Dome is removed."; } - Serial.println(" [[ConfigManager::Run()]]: 2!"); + //Serial.println(" [[ConfigManager::Run()]]: 2!"); // get current game from gameMan _game_to_play = _gameMan->get_current_game(); _new_game_selected = _game_to_play; - Serial.println(" [[ConfigManager::Run()]]: 3!"); + //Serial.println(" [[ConfigManager::Run()]]: 3!"); _serve_webinterface(); - Serial.println(" [[ConfigManager::Run()]]: 4!"); + //Serial.println(" [[ConfigManager::Run()]]: 4!"); if (_new_game_selected >= 0 && _new_game_selected != _game_to_play) { Log.info("New game selected %i", _new_game_selected); @@ -231,7 +231,7 @@ bool ConfigManager::Run() } - Serial.println(" [[ConfigManager::Run()]]: 5!"); + //Serial.println(" [[ConfigManager::Run()]]: 5!"); // test idea that we always attempt to reconnect every N seconds. // could make this last webpage-request dependent, so if webpage is currently active, don't need to do this bool _need_mdns_reconnect = (millis() - _last_request_time > 10000); @@ -262,9 +262,9 @@ bool ConfigManager::Run() // also set to active by default? // TODO it already is by default but should set back to HUB STAY ON mode if can't connect to wifi??? or at least not in HUB STAY OFF mode??? // also... we might need to put this in its own class at some point - Serial.println(" [[ConfigManager::Run()]]: 6!"); + //Serial.println(" [[ConfigManager::Run()]]: 6!"); _process_hub_mode(); - Serial.println(" [[ConfigManager::Run()]]: 7!"); + //Serial.println(" [[ConfigManager::Run()]]: 7!"); return true; } diff --git a/src/game-manager.cpp b/src/game-manager.cpp index f92debf..cc041e4 100644 --- a/src/game-manager.cpp +++ b/src/game-manager.cpp @@ -67,7 +67,7 @@ bool GameManager::Run() { if (_game_enabled) { - Serial.println(" [[GameManager::Run()]]: 1!"); + //Serial.println(" [[GameManager::Run()]]: 1!"); bool trial_done = false; // TODO simplify this / move to a function when cleaning up @@ -142,7 +142,7 @@ bool GameManager::Run() } _trial_just_done = trial_done; - Serial.println(" [[GameManager::Run()]]: 2!"); + //Serial.println(" [[GameManager::Run()]]: 2!"); } else { From c9a4ddf73ca10131056aeb8454765f597afbe06f Mon Sep 17 00:00:00 2001 From: asingularity Date: Mon, 26 Sep 2022 14:57:25 -0700 Subject: [PATCH 10/14] only memcheck every 10 sec --- examples/main/particle-test-local.ino | 2 +- library.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/main/particle-test-local.ino b/examples/main/particle-test-local.ino index 517251b..bd3e7f7 100644 --- a/examples/main/particle-test-local.ino +++ b/examples/main/particle-test-local.ino @@ -65,7 +65,7 @@ void loop() { // Serial.println("[[calling]]: gameMan.Run();"); gameMan.Run(); - if ((millis() - lastmemcheck) > 1000) { + if ((millis() - lastmemcheck) > 10000) { // Serial.print(Time.timeStr()); // Serial.println("[[calling]]: free memory"); diff --git a/library.properties b/library.properties index 902c852..7a6412b 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=hackerpet_plus_dev -version=0.1.70 +version=0.1.71 license=AGPL author=Csaba Petre maintainer=Csaba Petre From f9aebabd7d6311708c52ca473fdc80361e9ae787 Mon Sep 17 00:00:00 2001 From: asingularity Date: Wed, 28 Sep 2022 11:18:12 -0700 Subject: [PATCH 11/14] set library.properties back to hackerpet (prod) --- library.properties | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library.properties b/library.properties index 7a6412b..9273ef4 100644 --- a/library.properties +++ b/library.properties @@ -1,9 +1,9 @@ -name=hackerpet_plus_dev -version=0.1.71 +name=hackerpet_plus +version=0.1.108 license=AGPL author=Csaba Petre maintainer=Csaba Petre -sentence=(Dev Version!) Long-term cloud-less firmware! +sentence=(Alpha Version!) Long-term cloud-less firmware! category=Other url=http://hackerpet.com repository=https://github.com/CleverPet/hackerpet_plus/ From 3f16f81f91defc4f1ee65b61339c975943334bde Mon Sep 17 00:00:00 2001 From: asingularity Date: Wed, 28 Sep 2022 11:22:14 -0700 Subject: [PATCH 12/14] remaining MDNS files --- lib/MDNS/LICENSE | 21 +++++++++++++++++++++ lib/MDNS/README.md | 4 ++++ lib/MDNS/library.properties | 9 +++++++++ lib/MDNS/src/MDNS/Buffer.h | 1 + lib/MDNS/src/MDNS/Label.h | 1 + lib/MDNS/src/MDNS/MDNS.h | 1 + lib/MDNS/src/MDNS/Record.h | 1 + 7 files changed, 38 insertions(+) create mode 100644 lib/MDNS/LICENSE create mode 100644 lib/MDNS/README.md create mode 100644 lib/MDNS/library.properties create mode 100644 lib/MDNS/src/MDNS/Buffer.h create mode 100644 lib/MDNS/src/MDNS/Label.h create mode 100644 lib/MDNS/src/MDNS/MDNS.h create mode 100644 lib/MDNS/src/MDNS/Record.h diff --git a/lib/MDNS/LICENSE b/lib/MDNS/LICENSE new file mode 100644 index 0000000..abaf418 --- /dev/null +++ b/lib/MDNS/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) Mark Hornsby 2020 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/lib/MDNS/README.md b/lib/MDNS/README.md new file mode 100644 index 0000000..61423ae --- /dev/null +++ b/lib/MDNS/README.md @@ -0,0 +1,4 @@ +spark-core-mdns +=============== + +Multicast DNS and DNS-SD for the Spark Core diff --git a/lib/MDNS/library.properties b/lib/MDNS/library.properties new file mode 100644 index 0000000..03f0ba3 --- /dev/null +++ b/lib/MDNS/library.properties @@ -0,0 +1,9 @@ +name=MDNS +version=2.0.0 +license=MIT +author=Mark Hornsby +sentence=Support for multicast name and DNS service registration +# paragraph=a longer description of this library, always prepended with sentence when shown +# url=the url for the project +repository=https://github.com/mrhornsby/spark-core-mdns.git +# architectures=a list of supported boards if this library is hardware dependent, like particle-photon,particle-electron diff --git a/lib/MDNS/src/MDNS/Buffer.h b/lib/MDNS/src/MDNS/Buffer.h new file mode 100644 index 0000000..67d1997 --- /dev/null +++ b/lib/MDNS/src/MDNS/Buffer.h @@ -0,0 +1 @@ +#include "../Buffer.h" \ No newline at end of file diff --git a/lib/MDNS/src/MDNS/Label.h b/lib/MDNS/src/MDNS/Label.h new file mode 100644 index 0000000..e86c968 --- /dev/null +++ b/lib/MDNS/src/MDNS/Label.h @@ -0,0 +1 @@ +#include "../Label.h" \ No newline at end of file diff --git a/lib/MDNS/src/MDNS/MDNS.h b/lib/MDNS/src/MDNS/MDNS.h new file mode 100644 index 0000000..0817678 --- /dev/null +++ b/lib/MDNS/src/MDNS/MDNS.h @@ -0,0 +1 @@ +#include "../MDNS.h" \ No newline at end of file diff --git a/lib/MDNS/src/MDNS/Record.h b/lib/MDNS/src/MDNS/Record.h new file mode 100644 index 0000000..e92ec30 --- /dev/null +++ b/lib/MDNS/src/MDNS/Record.h @@ -0,0 +1 @@ +#include "../Record.h" \ No newline at end of file From 3dbee8472f7f3ade848a5e6f8a93cc1403fa1856 Mon Sep 17 00:00:00 2001 From: asingularity Date: Wed, 28 Sep 2022 12:16:28 -0700 Subject: [PATCH 13/14] move logHandler to main file; commented Serial.println statements become Log.trace --- examples/main/hackerpet_plus.ino | 23 ++++++++--- lib/MDNS/src/Label.cpp | 66 ++++++++++++++++---------------- lib/MDNS/src/MDNS.cpp | 62 +++++++++++++++--------------- src/config-manager.cpp | 16 ++++---- src/game-manager.cpp | 4 +- src/game_helper_functions.cpp | 9 ----- 6 files changed, 90 insertions(+), 90 deletions(-) diff --git a/examples/main/hackerpet_plus.ino b/examples/main/hackerpet_plus.ino index 5702c19..67c473a 100644 --- a/examples/main/hackerpet_plus.ino +++ b/examples/main/hackerpet_plus.ino @@ -25,6 +25,18 @@ #include "config-manager.h" #include "game-manager.h" + +// Use primary serial over USB interface for logging output (9600) +// Choose logging level here (ERROR, WARN, INFO) or TRACE +// *** important *** if you want to enable TRACE level debugging, this will display A LOT of logs. +// If you need to debug at that level, it is recommended to "slow down" the hub by executing the contents of the main loop() only i.e. once a second. + +SerialLogHandler logHandler(LOG_LEVEL_INFO, { // Logging level for all messages + { "app.hackerpet", LOG_LEVEL_ERROR }, // Logging level for library messages + { "app", LOG_LEVEL_INFO } // Logging level for application messages +}); + + // classes HubInterface hub; GameManager gameMan(&hub); // which game to play given gameId from config @@ -52,25 +64,24 @@ unsigned long FREE_MEMORY; // loop() runs over and over again, as quickly as it can execute. void loop() { - + Log.trace("[[calling]]: configMan.Run();"); // serve webpage, read/write eeprom as config changes - // Serial.println("[[calling]]: configMan.Run();"); configMan.Run(); - // Serial.println("[[calling]]: hub.Run(20);"); + Log.trace("[[calling]]: hub.Run(20);"); // run the hub // if testing on a particle photon by itself with no hub, comment this line to avoid seg fault hub.Run(20); // run the loop for the current active game - // Serial.println("[[calling]]: gameMan.Run();"); + Log.trace("[[calling]]: gameMan.Run();"); gameMan.Run(); // every 10 seconds, print the free memory as a serial heartbeat if ((millis() - lastmemcheck) > 10000) { - // Serial.print(Time.timeStr()); - // Serial.println("[[calling]]: free memory"); + Log.trace(Time.timeStr()); + Log.trace("[[calling]]: free memory"); FREE_MEMORY = System.freeMemory(); diff --git a/lib/MDNS/src/Label.cpp b/lib/MDNS/src/Label.cpp index 6fa7639..9dabbc1 100644 --- a/lib/MDNS/src/Label.cpp +++ b/lib/MDNS/src/Label.cpp @@ -77,24 +77,24 @@ bool mdns::Label::Reader::hasNext() { } uint8_t mdns::Label::Reader::next() { - //Serial.println(" mdns::Label::Reader::next: [1]"); + Log.trace(" mdns::Label::Reader::next: [1]"); c = buffer->readUInt8(); - //Serial.println(" mdns::Label::Reader::next: [2]"); + Log.trace(" mdns::Label::Reader::next: [2]"); while ((c & LABEL_POINTER) == LABEL_POINTER) { - //Serial.println(" mdns::Label::Reader::next: [3]"); + Log.trace(" mdns::Label::Reader::next: [3]"); if (buffer->available() > 0) { - //Serial.println(" mdns::Label::Reader::next: [4]"); + Log.trace(" mdns::Label::Reader::next: [4]"); uint8_t c2 = buffer->readUInt8(); - //Serial.println(" mdns::Label::Reader::next: [5]"); + Log.trace(" mdns::Label::Reader::next: [5]"); uint16_t pointerOffset = ((c & ~LABEL_POINTER) << 8) | c2; - //Serial.println(" mdns::Label::Reader::next: [6]"); + Log.trace(" mdns::Label::Reader::next: [6]"); buffer->mark(); - //Serial.println(" mdns::Label::Reader::next: [7]"); + Log.trace(" mdns::Label::Reader::next: [7]"); buffer->setOffset(pointerOffset); - //Serial.println(" mdns::Label::Reader::next: [8]"); + Log.trace(" mdns::Label::Reader::next: [8]"); c = buffer->readUInt8(); - //Serial.println(" mdns::Label::Reader::next: [9]"); + Log.trace(" mdns::Label::Reader::next: [9]"); } else { @@ -102,9 +102,9 @@ uint8_t mdns::Label::Reader::next() { return c; } - //Serial.println(" mdns::Label::Reader::next: [10]"); + Log.trace(" mdns::Label::Reader::next: [10]"); } - //Serial.println(" mdns::Label::Reader::next: [11]"); + Log.trace(" mdns::Label::Reader::next: [11]"); return c; } @@ -148,68 +148,68 @@ mdns::Label * mdns::Label::Iterator::getStartLabel() { mdns::Label * mdns::Label::Matcher::match(std::map labels, Buffer * buffer) { - //Serial.println(" mdns::Label::Matcher::match: [1]"); + Log.trace(" mdns::Label::Matcher::match: [1]"); Iterator * iterators[labels.size()]; - //Serial.println(" mdns::Label::Matcher::match: [2]"); + Log.trace(" mdns::Label::Matcher::match: [2]"); std::map::const_iterator i; uint8_t idx = 0; - //Serial.println(" mdns::Label::Matcher::match: [3]"); + Log.trace(" mdns::Label::Matcher::match: [3]"); for (i = labels.begin(); i != labels.end(); ++i) { iterators[idx++] = new Iterator(i->second); } - //Serial.println(" mdns::Label::Matcher::match: [4]"); + Log.trace(" mdns::Label::Matcher::match: [4]"); Reader * reader = new Reader(buffer); - //Serial.println(" mdns::Label::Matcher::match: [5]"); + Log.trace(" mdns::Label::Matcher::match: [5]"); while (reader->hasNext()) { - // Serial.println(" mdns::Label::Matcher::match: [6]"); + Log.trace(" mdns::Label::Matcher::match: [6]"); uint8_t size = reader->next(); uint8_t idx = 0; - // Serial.println(" mdns::Label::Matcher::match: [7]"); + Log.trace(" mdns::Label::Matcher::match: [7]"); for (uint8_t i = 0; i < labels.size(); i++) { iterators[i]->match(size); } - // Serial.println(" mdns::Label::Matcher::match: [8]"); + Log.trace(" mdns::Label::Matcher::match: [8]"); while(idx < size && reader->hasNext()) { - // Serial.println(" mdns::Label::Matcher::match: [8.1]"); + Log.trace(" mdns::Label::Matcher::match: [8.1]"); uint8_t c = reader->next(); - // Serial.println(" mdns::Label::Matcher::match: [8.2]"); + Log.trace(" mdns::Label::Matcher::match: [8.2]"); for (uint8_t i = 0; i < labels.size(); i++) { - // Serial.println(" mdns::Label::Matcher::match: [8.3]"); + Log.trace(" mdns::Label::Matcher::match: [8.3]"); iterators[i]->match(c); } - // Serial.println(" mdns::Label::Matcher::match: [8.4]"); + Log.trace(" mdns::Label::Matcher::match: [8.4]"); idx++; } - // Serial.println(" mdns::Label::Matcher::match: [9]"); + Log.trace(" mdns::Label::Matcher::match: [9]"); } - // Serial.println(" mdns::Label::Matcher::match: [10]"); + Log.trace(" mdns::Label::Matcher::match: [10]"); buffer->reset(); - // Serial.println(" mdns::Label::Matcher::match: [11]"); + Log.trace(" mdns::Label::Matcher::match: [11]"); Label * label = NULL; - // Serial.println(" mdns::Label::Matcher::match: [12]"); + Log.trace(" mdns::Label::Matcher::match: [12]"); if (reader->endOfName()) { uint8_t idx = 0; - // Serial.println(" mdns::Label::Matcher::match: [13]"); + Log.trace(" mdns::Label::Matcher::match: [13]"); while (label == NULL && idx < labels.size()) { - // Serial.println(" mdns::Label::Matcher::match: [14]"); + Log.trace(" mdns::Label::Matcher::match: [14]"); if (iterators[idx]->matched()) { label = iterators[idx]->getStartLabel(); } - // Serial.println(" mdns::Label::Matcher::match: [15]"); + Log.trace(" mdns::Label::Matcher::match: [15]"); idx++; } } -// Serial.println(" mdns::Label::Matcher::match: [16]"); +Log.trace(" mdns::Label::Matcher::match: [16]"); for (uint8_t i = 0; i < labels.size(); i++) { delete iterators[i]; } -// Serial.println(" mdns::Label::Matcher::match: [17]"); +Log.trace(" mdns::Label::Matcher::match: [17]"); delete reader; - // Serial.println(" mdns::Label::Matcher::match: [18]"); + Log.trace(" mdns::Label::Matcher::match: [18]"); return label; } diff --git a/lib/MDNS/src/MDNS.cpp b/lib/MDNS/src/MDNS.cpp index 3423c80..38577e6 100644 --- a/lib/MDNS/src/MDNS.cpp +++ b/lib/MDNS/src/MDNS.cpp @@ -140,54 +140,54 @@ bool mdns::MDNS::processQueries() { uint16_t n = udp->parsePacket(); if (n > 0) { - //Serial.println(" MDNS::processQueries(): buffer->read(udp);"); + Log.trace(" MDNS::processQueries(): buffer->read(udp);"); buffer->read(udp); - //Serial.println(" MDNS::processQueries(): udp->flush();"); + Log.trace(" MDNS::processQueries(): udp->flush();"); udp->flush(); - //Serial.println(" MDNS::processQueries(): getResponses();"); + Log.trace(" MDNS::processQueries(): getResponses();"); getResponses(); - //Serial.println(" MDNS::processQueries(): buffer->clear();"); + Log.trace(" MDNS::processQueries(): buffer->clear();"); buffer->clear(); - //Serial.println(" MDNS::processQueries(): writeResponses();"); + Log.trace(" MDNS::processQueries(): writeResponses();"); writeResponses(); - //Serial.println(" MDNS::processQueries(): returning"); + Log.trace(" MDNS::processQueries(): returning"); } return n > 0; } void mdns::MDNS::getResponses() { - // Serial.println(" MDNS::getResponses(): [1]"); + Log.trace(" MDNS::getResponses(): [1]"); QueryHeader header = readHeader(buffer); - // Serial.println(" MDNS::getResponses(): [2]"); + Log.trace(" MDNS::getResponses(): [2]"); if ((header.flags & 0x8000) == 0 && header.qdcount > 0) { uint8_t count = 0; - // Serial.println(" MDNS::getResponses(): [3]"); + Log.trace(" MDNS::getResponses(): [3]"); while (count++ < header.qdcount && buffer->available() > 0) { - //Serial.println(" MDNS::getResponses(): [4]"); + Log.trace(" MDNS::getResponses(): [4]"); Label * label = matcher->match(labels, buffer); - // Serial.println(" MDNS::getResponses(): [5]"); + Log.trace(" MDNS::getResponses(): [5]"); if (buffer->available() >= 4) { - // Serial.println(" MDNS::getResponses(): [6]"); + Log.trace(" MDNS::getResponses(): [6]"); uint16_t type = buffer->readUInt16(); - // Serial.println(" MDNS::getResponses(): [7]"); + Log.trace(" MDNS::getResponses(): [7]"); uint16_t cls = buffer->readUInt16(); - // Serial.println(" MDNS::getResponses(): [8]"); + Log.trace(" MDNS::getResponses(): [8]"); if (label != NULL) { - // Serial.println(" MDNS::getResponses(): [9]"); + Log.trace(" MDNS::getResponses(): [9]"); label->matched(type, cls); - // Serial.println(" MDNS::getResponses(): [10]"); + Log.trace(" MDNS::getResponses(): [10]"); } } else { - // Serial.println(" MDNS::getResponses(): [11]"); + Log.trace(" MDNS::getResponses(): [11]"); status = "Buffer underflow at index " + buffer->getOffset(); } - // Serial.println(" MDNS::getResponses(): [12]"); + Log.trace(" MDNS::getResponses(): [12]"); } - // Serial.println(" MDNS::getResponses(): [13]"); + Log.trace(" MDNS::getResponses(): [13]"); } - // Serial.println(" MDNS::getResponses(): [14]"); + Log.trace(" MDNS::getResponses(): [14]"); } mdns::MDNS::QueryHeader mdns::MDNS::readHeader(Buffer * buffer) { @@ -219,7 +219,7 @@ void mdns::MDNS::writeResponses() { } } - // Serial.println(" MDNS::writeResponses(): [1]"); + Log.trace(" MDNS::writeResponses(): [1]"); if (answerCount > 0) { buffer->writeUInt16(0x0); buffer->writeUInt16(0x8400); @@ -227,37 +227,37 @@ void mdns::MDNS::writeResponses() { buffer->writeUInt16(answerCount); buffer->writeUInt16(0x0); buffer->writeUInt16(additionalCount); - // Serial.println(" MDNS::writeResponses(): [2]"); + Log.trace(" MDNS::writeResponses(): [2]"); for (std::vector::const_iterator i = records.begin(); i != records.end(); ++i) { if ((*i)->isAnswerRecord()) { (*i)->write(buffer); } } - // Serial.println(" MDNS::writeResponses(): [3]"); + Log.trace(" MDNS::writeResponses(): [3]"); for (std::vector::const_iterator i = records.begin(); i != records.end(); ++i) { if ((*i)->isAdditionalRecord()) { (*i)->write(buffer); } } - // Serial.println(" MDNS::writeResponses(): [4]"); + Log.trace(" MDNS::writeResponses(): [4]"); } - // Serial.println(" MDNS::writeResponses(): [5]"); + Log.trace(" MDNS::writeResponses(): [5]"); if (buffer->available() > 0) { - // Serial.println(" MDNS::writeResponses(): [6]"); + Log.trace(" MDNS::writeResponses(): [6]"); udp->beginPacket(MDNS_ADDRESS, MDNS_PORT); - // Serial.println(" MDNS::writeResponses(): [7]"); + Log.trace(" MDNS::writeResponses(): [7]"); buffer->write(udp); - // Serial.println(" MDNS::writeResponses(): [8]"); + Log.trace(" MDNS::writeResponses(): [8]"); udp->endPacket(); - // Serial.println(" MDNS::writeResponses(): [9]"); + Log.trace(" MDNS::writeResponses(): [9]"); } - // Serial.println(" MDNS::writeResponses(): [10]"); + Log.trace(" MDNS::writeResponses(): [10]"); for (std::map::const_iterator i = labels.begin(); i != labels.end(); ++i) { i->second->reset(); } - // Serial.println(" MDNS::writeResponses(): [11]"); + Log.trace(" MDNS::writeResponses(): [11]"); for (std::vector::const_iterator i = records.begin(); i != records.end(); ++i) { (*i)->reset(); } diff --git a/src/config-manager.cpp b/src/config-manager.cpp index 259da10..a5a89e4 100644 --- a/src/config-manager.cpp +++ b/src/config-manager.cpp @@ -199,7 +199,7 @@ bool ConfigManager::Run() // what message to display on the webpage for hub status - //Serial.println(" [[ConfigManager::Run()]]: 1!"); + Log.trace(" [[ConfigManager::Run()]]: 1!"); _display_error_msg = "Your hub is working."; if (_hub->IsHubOutOfFood()) { @@ -218,17 +218,17 @@ bool ConfigManager::Run() _display_error_msg = "Dome is removed."; } - // Serial.println(" [[ConfigManager::Run()]]: 2!"); + Log.trace(" [[ConfigManager::Run()]]: 2!"); // get current game from game manager _game_to_play = _gameMan->get_current_game(); _new_game_selected = _game_to_play; - //Serial.println(" [[ConfigManager::Run()]]: 3!"); + Log.trace(" [[ConfigManager::Run()]]: 3!"); _serve_webinterface(); - //Serial.println(" [[ConfigManager::Run()]]: 4!"); + Log.trace(" [[ConfigManager::Run()]]: 4!"); if (_new_game_selected >= 0 && _new_game_selected != _game_to_play) { Log.info("New game selected %i", _new_game_selected); @@ -244,7 +244,7 @@ bool ConfigManager::Run() // on some networks, mdns occasionally fails and the domain clevepet.local stops working; need to attempt reconnect // since we don't have a conclusive way to determine if it is broken, we for now blindly attempt reconnect every 10 seconds if there's no request in that time - //Serial.println(" [[ConfigManager::Run()]]: 5!"); + Log.trace(" [[ConfigManager::Run()]]: 5!"); bool _need_mdns_reconnect = (millis() - _last_request_time > 10000); @@ -268,7 +268,7 @@ bool ConfigManager::Run() } _process_hub_mode(); - //Serial.println(" [[ConfigManager::Run()]]: 7!"); + Log.trace(" [[ConfigManager::Run()]]: 7!"); return true; } @@ -910,9 +910,7 @@ bool ConfigManager::_process_set_hub_mode_req(String req_str) int hub_mode_html_index = req_str.indexOf("hub_mode\""); // "hub_mode": Log.info("This is a HUB MODE post request."); - //Log.print("*******\n"); - //Log.print(thing + "\n"); - //Log.print("*-------------*\n"); + String tmp_2 = req_str.substring(hub_mode_html_index + 10); int index_stop = tmp_2.indexOf("}"); tmp_2 = tmp_2.substring(0, index_stop); diff --git a/src/game-manager.cpp b/src/game-manager.cpp index cc041e4..ce0c647 100644 --- a/src/game-manager.cpp +++ b/src/game-manager.cpp @@ -67,7 +67,7 @@ bool GameManager::Run() { if (_game_enabled) { - //Serial.println(" [[GameManager::Run()]]: 1!"); + Log.trace(" [[GameManager::Run()]]: 1!"); bool trial_done = false; // TODO simplify this / move to a function when cleaning up @@ -142,7 +142,7 @@ bool GameManager::Run() } _trial_just_done = trial_done; - //Serial.println(" [[GameManager::Run()]]: 2!"); + Log.trace(" [[GameManager::Run()]]: 2!"); } else { diff --git a/src/game_helper_functions.cpp b/src/game_helper_functions.cpp index 324ed92..d99ab85 100644 --- a/src/game_helper_functions.cpp +++ b/src/game_helper_functions.cpp @@ -4,15 +4,6 @@ #include // random_shuffle -// Use primary serial over USB interface for logging output (9600) -// Choose logging level here (ERROR, WARN, INFO) -SerialLogHandler logHandler(LOG_LEVEL_INFO, { // Logging level for all messages - { "app.hackerpet", LOG_LEVEL_ERROR }, // Logging level for library messages - { "app", LOG_LEVEL_INFO } // Logging level for application messages -}); - - - /** * Helper functions * ---------------- From 5d3a8b8fde3c77ad540fbce43d55bd6062b714fb Mon Sep 17 00:00:00 2001 From: asingularity Date: Wed, 28 Sep 2022 15:13:17 -0700 Subject: [PATCH 14/14] cleaning up config manager --- src/config-manager.cpp | 91 ++++++++++++++++-------------------------- 1 file changed, 35 insertions(+), 56 deletions(-) diff --git a/src/config-manager.cpp b/src/config-manager.cpp index a5a89e4..a820f04 100644 --- a/src/config-manager.cpp +++ b/src/config-manager.cpp @@ -267,7 +267,10 @@ bool ConfigManager::Run() } + // process hub mode (stay on, stay off, scheduler) + _process_hub_mode(); + Log.trace(" [[ConfigManager::Run()]]: 7!"); return true; @@ -276,12 +279,9 @@ bool ConfigManager::Run() bool ConfigManager::_process_hub_mode() { - - // compare _hub_mode vs _last_hub_mode (set at the end of this function) - if (_hub_mode != _last_hub_mode) { - // there may not be anything to set here ... + // currently, there's no specific action to take when hub mode _changes_ ... } // determine hub state: active vs. standby, based on mode (and schedule, if mode is scheduler) @@ -298,17 +298,10 @@ bool ConfigManager::_process_hub_mode() } else if (_hub_mode == _HUB_MODE_SCHEDULED) { - // use: - - // _weekday_from: 06:30 - // _weekday_to - // _weekend_from - // _weekend_to - - // get: - // current time - // current day of the week -> weekday or weekend + // determine hub state based on schedule, current time, and current day of the week + // get current time and weekday vs. weekend + int hour_now = Time.hour(); int minute_now = Time.minute(); int weekday_now = Time.weekday(); @@ -318,6 +311,8 @@ bool ConfigManager::_process_hub_mode() String to_hour = " "; String to_minute = " "; + // get from/to hour and minute for hub to be on, from current scheduler settings (_weekend_from, _weekend_to, _weekday...) and current day of the week + if (weekday_now == 1 || weekday_now == 7) // it is a weekend { from_hour[0] = _weekend_from[0]; @@ -347,7 +342,6 @@ bool ConfigManager::_process_hub_mode() to_minute[1] = _weekday_to[4]; } - int day_minutes_now = hour_now * 60 + minute_now; int day_minutes_from = from_hour.toInt() * 60 + from_minute.toInt(); @@ -396,7 +390,7 @@ bool ConfigManager::_process_hub_mode() new_hub_state = _HUB_STATE_ACTIVE; } - // TODO have to count _kibbles_eaten_today !! + // count _kibbles_eaten_today (retrieve from game manager) _kibbles_eaten_today = _gameMan->get_kibbles_eaten(); // if kibbles are above limit, override new_hub_state to standby @@ -405,9 +399,9 @@ bool ConfigManager::_process_hub_mode() new_hub_state = _HUB_STATE_STANDBY; } - // TODO reset kibbles eaten when needed! (when it is after midnight and previous time was before) - // based on: Time.day, Time.last_day ? - this is day of the month! check not equals - // Time.day() + // reset kibbles eaten when needed (when it is after midnight and previous time was before) + // based on: Time.day, Time.last_day (day of the month) + int day_now = Time.day(); bool reset_kibbles = false; @@ -431,45 +425,39 @@ bool ConfigManager::_process_hub_mode() if (new_hub_state == _HUB_STATE_ACTIVE) { - - // for now, we are going to ignore the indicator light - - // _logger->Log("SI::OnDesiredStatus: setting _activity_state = ACTIVITY_STATE_ACTIVE", Logger::LOG_LEVEL_LIGHT_CONTEXT); - // IndicatorState = IL_SI_ACTIVE; - - - // this just set _active_mode flag in old firmware and that's all... - // _dli->SetActiveMode(true); - + // reference from cleverpet cloud-based firmware + // (for now, we are going to ignore the indicator light): + // _logger->Log("SI::OnDesiredStatus: setting _activity_state = ACTIVITY_STATE_ACTIVE", Logger::LOG_LEVEL_LIGHT_CONTEXT); + // IndicatorState = IL_SI_ACTIVE; + // this just set _active_mode flag + // _dli->SetActiveMode(true); + _hub->SetButtonAudioEnabled(true); _hub->SetLightEnabled(true); _hub->UpdateButtonAudioEnabled(); // inform game manager of hub state - // technically, only need to do this if it changed. - // should we just have it skip the game loop? _gameMan->set_game_enabled(true); + // set new hub state as the current state _hub_state = new_hub_state; - } else if (new_hub_state == _HUB_STATE_STANDBY) { - // for now, we are going to ignore the indicator light - - // _logger->Log("SI::OnDesiredStatus: setting _activity_state = ACTIVITY_STATE_STANDBY", Logger::LOG_LEVEL_LIGHT_CONTEXT); - // if (_max_kibbles_light_on) - // { - // IndicatorState = IL_SI_MAX_KIBBLES_DEPLETED; - // } - // else - // { - // IndicatorState = IL_SI_STANDBY; - // } - // + // reference from cleverpet cloud-based firmware + // (for now, we are going to ignore the indicator light): + // _logger->Log("SI::OnDesiredStatus: setting _activity_state = ACTIVITY_STATE_STANDBY", Logger::LOG_LEVEL_LIGHT_CONTEXT); + // if (_max_kibbles_light_on) + // { + // IndicatorState = IL_SI_MAX_KIBBLES_DEPLETED; + // } + // else + // { + // IndicatorState = IL_SI_STANDBY; + // } - // this just set _active_mode flag in old firmware and that's all... - // _dli->SetActiveMode(false); + // this just set _active_mode flag in old firmware and that's all... + // _dli->SetActiveMode(false); // only swap from ACTIVE to STANDBY if a game ended; but allow swap from INIT to STANDBY regardless if ((_hub_state == _HUB_STATE_ACTIVE && _gameMan->trial_just_done()) || (_hub_state == _HUB_STATE_INIT)) @@ -487,8 +475,6 @@ bool ConfigManager::_process_hub_mode() { Log.info("ERROR invalid hub state!"); } - - } _last_hub_mode = _hub_mode; @@ -499,9 +485,6 @@ bool ConfigManager::_process_hub_mode() bool ConfigManager::_serve_webinterface() { - //int new_game_selected = -1; - //int overrideable_next_game = _next_game_to_play; - _webclient = _webserver.available(); bool request_finished = false; if (_webclient.connected()) @@ -521,7 +504,7 @@ bool ConfigManager::_serve_webinterface() Log.info("--- SERVER FINISHED PROCESSING REQUEST ---"); } - delay (1); //That is a hack to allow the browser to receive the data + delay (1); //That is a hack to allow the browser to receive the data (this is from the original http server code library we are using) _webclient.stop(); return true; } @@ -553,10 +536,6 @@ bool ConfigManager::_read_from_client(bool & request_finished, String & response bool ConfigManager::_process_request(String req_str) { - - //Log.info("request string:"); - //Log.print(req_str); - // different types of requests bool req_get = req_str.substring(0, 3).equalsIgnoreCase("GET");