nixuchen

macos安装ESP8266_RTOS_SDK开发环境

一、安装python3环境:

      brew instsall python3

      成功安装后运行python3得到如下界面即安装成功

二、获取esp8266 sdk:

cd ~/esp

git clone –recursive https://github.com/espressif/ESP8266_RTOS_SDK.git

三、获取Toolchain

mkdir -p ~/espcd ~/esp

tar -xzf ~/Downloads/xtensa-lx106-elf-macos-1.22.0-100-ge567ec7-5.2.0.tar.gz

四、设置环境变量

PATH=${PATH}:~/esp/xtensa-lx106-elf/bin
export IDF_PATH=~/esp/ESP8266_RTOS_SDK
export ELF=~/esp/xtensa-lx106-elf/bin

五、Mac_OSX_VCP_Driver驱动安装:

https://www.silabs.com/developers/usb-to-uart-bridge-vcp-drivers?tab=downloads

双击install CP210x VCP Driver.app进行安装

六、查找usb驱动名

插入esp8266

命令行输入命令:ls /dev/cu.*

cu.usb开头的即为您的esp8266 驱动名复制下来:/dev/cu.usbserial-14210

七、设置 make menuconfig

default serial port 修改成您的esp8266的串口名,就是刚刚复制下来的:/dev/cu.usbserial-14210(根据您实际情况进行调整,不要直接复制文章内容)

8.编译测试

make 编译代码

make flash 刷入固件

make monitor 可以看到代码运行情况

通过iphone控制mac远程开机

Using a handy network feature built into OS X and supported by most modern Macs, you can remotely wake a Mac from sleep using an iPhone (or iPod touch, iPad, and Android too). This is done using something called Wake On LAN (WOL), and it’s easy to set up in Mac OS X and use from a smartphone with the help of a free app. The result is basically the total opposite of the remote sleep tricks we’ve covered before, and instead of remotely sleeping a machine, you can remotely wake it instead, having the Mac ready for general network access or just quicker use. Let’s go over how to set this up.
First: Set Up the Mac for Wake On LAN Support

Enabling Wake On LAN support on supported Macs is simple:

Make sure the Mac is connected to a network
Open System Preferences from the  Apple menu and go to “Energy Saver” control panel
Go to the “Power Adapter” tab and check the box for “Wake for Wi-Fi network access” (may be “Wake for network access” if device has multiple networking options) – this enables Wake On LAN in OS X

Enable Wake On LAN in Mac OS X
Now go back to the primary System Prefs window and choose “Network”
Select ‘Wi-Fi’ from the sidebar and note the machines IP address provided to the right

If you don’t see the “Wake for network access” option in the Energy Saver control panel, the Mac probably does not support the feature.

It is also possible to get the Mac’s IP address from the Sharing control panel or command line, you will need this to match the ID of the Mac in question when you’re setting up WOL from iOS in a moment.
Second: Configure the iPhone App for Waking the Mac

Now you’ll want to preconfigure the iOS app (or Android app, more on that below) to have the Macs network information on hand, allowing for the remote wake trick to be used:

Download an iOS app with WOL (Wake On LAN) support – Fing is multi-use and free which is what we’ll cover here (we like it for other uses too), but Mocha WOL is also free and does the job, or you can use a paid app like NetStatus
Join the same wi-fi network as the Mac, then run Fing and tap the refresh button to scan the network and locate the Mac you want to wake up
Select the Mac based on IP address, and give it a name, like “Wake On LAN Home”
Scroll down and tap on “Wake On Lan” (yes do this even though the Mac is not yet asleep) – now the Mac should be saved in the list based on the hardwares MAC address, even if the IP address changes

Using Wake On LAN in iOS

适配Android 12的行为变更—–精确的闹钟权限

为了鼓励应用节省系统资源,以 Android 12 及更高版本为目标平台且设置了精确的闹钟的应用必须能够访问“闹钟和提醒”功能,该功能显示在系统设置的特殊应用访问权限屏幕中。如需获取这种特殊应用访问权限,需在清单中请求 SCHEDULE_EXACT_ALARM 权限。

开发者网站请参考:

行为变更:以 Android 12 为目标平台的应用 | Android Developers

   简单来说就是代码中如果使用了setAlarmClock()、setExact()、setExactAndAllowWhileIdle()这几种方法,则设置的是精准的闹钟。在Android12环境下,调用这些方法时,如果SCHEDULE_EXACT_ALARM权限未打开,应用就会crash(做之前先测试一下,要是权限关闭以后,调用这些方法,要是应用不会crash,应该不需要对应)。所以,在调用这些方法时,要增加权限检查。

应对方法:

(1).申请权限

(2).跳转到授权画面

Google Pixel的处理流程:在一打开应用的时候就进行权限检查,如果check到SCHEDULE_EXACT_ALARM权限没打开,就使用toast提示用户打开授权界面,若用户不打开设置的闹钟都不好用(我的建议是弹dialog,要是用户拒绝就直接退出应用,省得后面麻烦)

Uri uri = Uri.parse("package:"+this.getPackageName());
Intent i = new Intent(Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM,uri);
startActivity(i,200);

SCHEDULE_EXACT_ALARM权限 授权画面

(3).判断是否具有权限

alarmManager=(AlarmManager)getSystemService(Context.ALARM_SERVICE);
boolean  hasPermission = alarmManager.canScheduleExactAlarms();//true:有权限,false:没有权限
if(hasPermission){
    setAlarmClock();//设置精准闹钟的方法
    setExact();
    setExactAndAllowWhileIdle();
}else{
    //如果没检查到权限,应该做出相应的处理
    //(1).什么都不做,写一条log。如果权限关闭闹钟将无法使用
    //(2).设置不精准的闹钟
    //(3).使用dialog、toast等提示用户打开权限(具体项目,具体设计,不建议在每次设置精准闹钟时候都对用户进行提示,这样的用户体验感不好)
}

注意点:

1.如果用户在SCHEDULE_EXACT_ALARM权限打开的时候设置闹钟,在闹钟到点前将闹钟关闭,到时间闹钟是不会响的,如果用户发现闹钟到点没响,就将SCHEDULE_EXACT_ALARM权限打开,闹钟可以响(闹钟过时,闹钟会被miss掉)

对应方法:设定一个广播接收器(静态,动态都可以),接收”AlarmManager.ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED”
这里要注意:只有在打开精准闹钟权限的时候才能收到广播;关闭时是收不到的,只能每次使用方法的时候checkPermission。
如果收不到广播的话,在终端运行以下命令,启用行为更:(模拟器也要运行)
adb shell am compat enable REQUIRE_EXACT_ALARM_PERMISSION [packageName]

正常来说,SCHEDULE_EXACT_ALARM权限是默认打开的,用户应该也不会找到这个将它关闭,更不太可能进行这么非人类的操作,但是我们作为开发者应该考虑滴全面些。我就打算等Android 12适配了,我就给各个手机厂商找茬去。Google Pixel已经被我找过一次茬了,我这里面说的情况,Google就还没做出处理(11月为止)。

2.App info和System Setting都有SCHEDULE_EXACT_ALARM 权限,它们俩的授权界面虽然长得一样,但是是不一样的界面。这将会导致一个问题,要是在App info中将权限关闭,在跳转授权界面的时候可能会跳转两个授权界面。
对应方法:在点击跳转按钮的时候再startActivity,这样就能把App info的授权界面(AlarmsAndRemindersAppActivity)给覆盖掉

public void createAlertDialog() {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setMessage(R.string.extra_alarm_permission_descript_title);
        builder.setPositiveButton(R.string.extra_alarm_permission_turn_on, new DialogInterface.OnClickListener() {
            Uri uri = Uri.parse("package:" + "com.android.deskclock");
            Intent intent = new Intent(Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM, uri);
            public void onClick(DialogInterface dialog, int which) {
                startActivity(intent);
            }
        });
        builder.setNegativeButton(R.string.extra_alarm_permission_ok, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {

            }
        });
        mExtraAlarmDialog = builder.create();
        mExtraAlarmDialog.setCancelable(false);
        mExtraAlarmDialog.show();
    }

options has an unknown property ‘disableHostCheck‘. These properties are valid:

提示:options has an unknown property ‘disableHostCheck’. These properties are valid:
在这里插入图片描述
根据报错提示
在webpack 5 中disableHostCheck应该被遗弃了
查看文档了解到需将 disableHostCheck:true
替换为
historyApiFallback: true,
allowedHosts: “all”,

重新配置vue.config.js

devServer: {
historyApiFallback: true,
allowedHosts: “all”,
}

console.log not work

In my case, all console messages were not showing because I had left a string in the “filter” textbox.

Remove the filter it by clicking the X as shown:

enter image description here

如何解决在 Python 中运行 Lambda 代码时收到的“Unable to import module”错误?

简短描述

通常情况下收到此错误的原因是 Lambda 环境在 Python 代码中找不到指定的库。这是因为 Lambda 没有预先封装所有 Python 库。

要解决此错误,请创建一个部署程序包或 Lambda 层,其中包含要在 Lambda 的 Python 代码中使用的库。

重要提示:确保把为 Python 导入的库放在 /python 文件夹中。

解决方法

注意:以下步骤展示的是如何创建 Lambda 层,并非部署程序包。这是因为您可以跨多个 Lambda 函数重复使用 Lambda 层。每个 Lambda 运行时将特定的 /opt 目录文件夹添加到 PATH 变量中。如果该层使用相同的文件夹结构,则 Lambda 函数的代码可以在不指定路径的情况下访问该层内容。

最佳实践是在建立 Lambda 运行时的同一操作系统上创建 Lambda 层。例如,Python 3.8 基于 Amazon Linux 2 Amazon Machine Image (AMI)。但是,Python 3.7 和 Python 3.6 以 Amazon Linux AMI 为基础。

要为 Python 3.8 库创建 Lambda 层,请执行以下操作:

1.    在 AWS Cloud9 控制台中,使用 Amazon Linux 2 AMI 创建一个 Amazon Elastic Compute Cloud (Amazon EC2) 实例。有关说明,请参阅《AWS Cloud9 用户指南》中的创建 EC2 环境

2.    创建一个 AWS Identity and Access Management (IAM) 策略,其将赋予调用 PublishLayerVersion API 操作的权限。

示例,IAM 策略语句将赋予调用 PublishLayerVersion API 操作的权限

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": "lambda:PublishLayerVersion",
            "Resource": "*"
        }
    ]
}

3.    创建一个 IAM 角色将 IAM 策略附上到该角色。然后,将 IAM 角色附上到 Amazon EC2 实例

注意:您的 EC2 实例现在拥有权限,可为 PublishLayerVersion API 调用上载 Lambda 层。

4.    打开您的 AWS Cloud9 Amazon EC2 环境。然后,通过运行以下命令安装 Python 3.8 和 pip3:

$ sudo amazon-linux-extras install python3.8
$ curl -O https://bootstrap.pypa.io/get-pip.py
$ python3.8 get-pip.py --user

5.    通过运行以下命令,创建一个 python 文件夹:

$ mkdir python

6.    通过运行以下命令,将 Pandas 库文件安装到 python 文件夹中:

重要提示:将 Pandas 替换为您要导入的 Python 库的名称。

$ python3.8 -m pip install pandas -t python/

7.    通过运行以下命令,将 python 文件夹的内容压缩到 layer.zip 文件中:

$ zip -r layer.zip python

8.    通过运行以下命令发布 Lambda 层:

重要提示:将 us-east-1 替换为您的 Lambda 函数所在的 AWS 区域。

$ aws lambda publish-layer-version --layer-name pandas-layer --zip-file fileb://layer.zip --compatible-runtimes python3.8 --region us-east-1

9.    向您的 Lambda 函数添加层

Govmomi获取虚拟机列表

基本思路

先获取所有虚拟机信息,再根据虚拟机所属集群分类,但实际操作中并未在虚拟机信息中查找到所属集群信息。
退而求其次,先获取主机和虚拟机信息,根据虚拟机所属主机分类,导出后手动对其集群分类。

安装Govmomi

1go get -u github.com/vmware/govmomi

链接到vSphere

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
var client *vim25.Clien
var ctx = context.Background()
const (
VSPHERE_IP = “xxx”
VSPHERE_USERNAME = “xxx”
VSPHERE_PASSWORD = “xxx”
Insecure = true
)
// NewClient 链接vmware
func NewClient() *vim25.Client {

u := &url.URL{
Scheme: “https”,
Host: VSPHERE_IP,
Path: “/sdk”,
}

u.User = url.UserPassword(VSPHERE_USERNAME, VSPHERE_PASSWORD)
client, err := govmomi.NewClient(ctx, u, Insecure)
if err != nil {
panic(err)
}
return client.Client
}

获取主机信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
// VmsHost 主机结构体
type VmsHost struct {
Name string
Ip string
}
// VmsHosts 主机列表结构体
type VmsHosts struct {
VmsHosts []VmsHost
}
// NewVmsHosts 初始化结构体
func NewVmsHosts() *VmsHosts {
return &VmsHosts{
VmsHosts: make([]VmsHost, 10),
}
}

// 虚拟机表
type Vm struct {
gorm.Model
Uuid string `gorm:”type:varchar(40);not null;unique;comment:’虚拟机id'”`
Vc string `gorm:”type:varchar(30);comment:’Vcenter Ip'”`
Esxi string `gorm:”type:varchar(30);comment:’Esxi Id'”`
Name string `gorm:”type:varchar(90);comment:’Vm名字'”`
Ip string `gorm:”type:varchar(20);comment:’Vm ip'”`
PowerState string `gorm:”type:varchar(20);comment:’Vm state'”`
}

// AddHost 新增主机
func (vmshosts *VmsHosts) AddHost(name string, ip string) {
host := &VmsHost{name, ip}
vmshosts.VmsHosts = append(vmshosts.VmsHosts, *host)
}
// SelectHost 查询主机ip
func (vmshosts *VmsHosts) SelectHost(name string) string {
ip := “None”
for _, hosts := range vmshosts.VmsHosts {
if hosts.Name == name {
ip = hosts.Ip
}
}
return ip
}

// GetHosts 读取主机信息
func GetHosts(client *vim25.Client, vmshosts *VmsHosts) {
m := view.NewManager(client)
v, err := m.CreateContainerView(ctx, client.ServiceContent.RootFolder, []string{“HostSystem”}, true)
if err != nil {
panic(err)
}
defer v.Destroy(ctx)
var hss []mo.HostSystem
err = v.Retrieve(ctx, []string{“HostSystem”}, []string{“summary”}, &hss)
if err != nil {
panic(err)
}
// fmt.Printf(“主机名:\t%s\n”, hss[0].Summary.Host.Value)
// fmt.Printf(“IP:\t%s\n”, hss[0].Summary.Config.Name)
for _, hs := range hss {
vmshosts.AddHost(hs.Summary.Host.Value, hs.Summary.Config.Name)
}
}

获取虚拟机信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// GetVms获取所有vm信息
func GetVms(client *vim25.Client, vmshosts *VmsHosts) {
m := view.NewManager(client)
v, err := m.CreateContainerView(ctx, client.ServiceContent.RootFolder, []string{“VirtualMachine”}, true)
if err != nil {
panic(err)
}
defer v.Destroy(ctx)
var vms []mo.VirtualMachine
err = v.Retrieve(ctx, []string{“VirtualMachine”}, []string{“summary”, “runtime”, “datastore”}, &vms)
if err != nil {
panic(err)
}
// 输出虚拟机信息到csv
file, _ := os.OpenFile(“./vms.csv”, os.O_WRONLY|os.O_CREATE, os.ModePerm)
//防止中文乱码
file.WriteString(“\xEF\xBB\xBF”)
w := csv.NewWriter(file)
w.Write([]string{“宿主机”, “虚拟机”, “系统”, “状态”, “IP地址”, “资源”})
w.Flush()
for _, vm := range vms {
//虚拟机资源信息
res := strconv.Itoa(int(vm.Summary.Config.MemorySizeMB)) + ” MB ” + strconv.Itoa(int(vm.Summary.Config.NumCpu)) + ” vCPU(s) ” + units.ByteSize(vm.Summary.Storage.Committed+vm.Summary.Storage.Uncommitted).String()
w.Write([]string{vmshosts.SelectHost(vm.Summary.Runtime.Host.Value), vm.Summary.Config.Name, vm.Summary.Config.GuestFullName, string(vm.Summary.Runtime.PowerState), vm.Summary.Guest.IpAddress, res})
w.Flush()
}
file.Close()

// 批量插入到数据库
var modelVms []*Vm
for _, vm := range vms {
modelVms = append(modelVms,&Vm{
Uuid: vm.Summary.Config.Uuid,
Vc: VSPHERE_IP,
Esxi: vm.Summary.Runtime.Host.Value,
Name: vm.Summary.Config.Name,
Ip: vm.Summary.Guest.IpAddress,
PowerState: string(vm.Summary.Runtime.PowerState),
})
}
}

AWS EC2 启用 IPv6 小记

日期:2018-04-30
更新:2018-04-30一开始以为 AWS EC2 启用 IPv6 会像 DigitalOcean 那样简单粗暴,创建实例的时候打个勾就好。没想到 AWS 家大业大,各个组件相互关联,折腾了一圈才弄明白,特此备份。需要协同修改有五个地方,分别是 VPC 、SubnetSecurity groups 和实例的网络设置,理论上只有第一个实例需要如此折腾,之后相同 VPCSubnet 和 Security groups 的实例应当可以直接获取 IPv6 的地址。VPC找到当前实例所属的 VPC 然后选择 Edit CIDRs然后点 Add IPv6 CIDR 就完事了:新建的 VPC 直接选择 Amazon provided IPv6 CIDR block 就可以了:Subnet同样的,找到当前实例所属的 Subnet 然后选择 Edit IPv6 CIDRs新建的 Subnet 直接输入想要的 IPv6 block 就可以了(一般从 00 开始,多个 Subnet 后续可以指定 0102,诸如此类):Security groups如果用户想要通过 IPv6 访问实例,还需要设置防火墙的相应规则,一般来说允许所有地址就是在 Inbound 的 Source 里设置 ::/0实例网络设置进入当前实例的 Networking – Manage IP Addresses,然后选择 Assign new IP 即可:参考引用IPv6 Support for EC2 Instances in Virtual Private Clouds

补充一下,如果需要开启 IPv6 公网访问,需要添加一条路由规则,具体见:
https://docs.aws.amazon.com/vpc/latest/userguide/vpc-migrate-ipv6.html#vpc-migrate-ipv6-routes