摩斯电码(Morse code),想必大家都是听说过的,虽然是一种相对古老的编码,但即使是在今天,也被众多业余无线电爱好者使用。
那么我们可以拿它来怎么玩呢?报一下IP吧!
上一篇post写了树莓派自动发送IP到邮箱这种方式,那么这次就来演示一下摩斯电码的方式吧。
你只需要一个树莓派、一个小小的蜂鸣器,另加几根导线,就可以开工了!自然,这一次我们也会使用wiringPi这个第三方库,安装过程什么的就略去吧。
我们这里取的时间标准是:滴=1t,嗒=3t,滴嗒间=1t,每个字符间=3t,.(IPv4中每段分隔的点号)、:(IPv6中每段分隔的冒号)=7t。
既然是使用Morse code,那么我们总得有个表吧。考虑到可能会有IPv6地址,我们的表就是0-9A-F了。
/** * @brief Part of morse code table * * 1 .---- * 2 ..--- * 3 ...-- * 4 ....- * 5 ..... * 6 -.... * 7 --... * 8 ---.. * 9 ----. * 0 ----- * A .- * B -... * C -.-. * D -.. * E . * F ..-. */ int table[16][5] = { {3, 3, 3, 3, 3}, {1, 3, 3, 3, 3}, {1, 1, 3, 3, 3}, {1, 1, 1, 3, 3}, {1, 1, 1, 1, 3}, {1, 1, 1, 1, 1}, {3, 1, 1, 1, 1}, {3, 3, 1, 1, 1}, {3, 3, 3, 1, 1}, {3, 3, 3, 3, 1}, {1, 3}, {3, 1, 1, 1}, {3, 1, 3, 1}, {3, 1, 1}, {1}, {1, 1, 3, 1} };
表中的1便是滴对应的1t,3则是嗒对应的3t。接下来便是获取IP地址。
void get_ip_from(const char * interface) { struct ifaddrs * interfaces; char str[INET_ADDRSTRLEN] = { 0 }; if (getifaddrs(&interfaces)) return; struct ifaddrs * address = interfaces; while (address) { if(address->ifa_addr->sa_family == AF_INET) { if (strcmp(address->ifa_name, interface) == 0) { inet_ntop(AF_INET, &((struct sockaddr_in *)address->ifa_addr)->sin_addr, str, INET_ADDRSTRLEN); sprintf(ip, "%s", str); break; } } address = address->ifa_next; } freeifaddrs(interfaces); }
IP拿到手之后,就可以开始发送Morse code了!
#define BUZZER_PIN 0 // 我们的蜂鸣器接在GPIO0上 #define INTERVAL_BASE 300 // ms #define CHARS 3 #define DI_DA 1 #define SEPARATOR 7 void ring(int duration) { digitalWrite (BUZZER_PIN, HIGH); delay(INTERVAL_BASE * duration); } void quiet(int duration) { digitalWrite (BUZZER_PIN, LOW); delay(INTERVAL_BASE * duration); } void buzz() { for (int i = 0; ; i++) { char text = ip[i]; if (text == '\0') { break; } else if (text == '.' || text == ':') { quiet(SEPARATOR); } else if (text >= '0' && text <= '9') { int * durations = table[text - '0']; for (int t = 0; t < 4; t++) { ring(durations[t]); quiet(DI_DA); } ring(durations[5]); } else if (text >= 'A' && text <= 'F') { int * durations = table[text - 'A' + 10]; for (int t = 0; t < 4; t++) { ring(durations[t]); quiet(DI_DA); } ring(durations[5]); } else if (text >= 'a' && text <= 'f') { int * durations = table[text - 'A' + 10]; for (int t = 0; t < 4; t++) { ring(durations[t]); quiet(DI_DA); } ring(durations[5]); } quiet(CHARS); } }
最后的main~
int main(){ wiringPiSetup() ; pinMode(BUZZER_PIN, OUTPUT); ip = (char *)malloc(sizeof(char) * 64); memset(ip, 0, sizeof(char) * 64); get_ip_from("wlan0"); printf("wlan0: %s\n",ip); buzz(); quiet(0); free(ip); return 0; }
你可以在我的Github上下载完整代码,buzzer_ip。