草庐IT

工业4.0 智能工厂简单学习项目

尊治 2023-04-04 原文

随着社会的发展,工厂智能化的步骤越来越快,信息和数据越来越重要,MES,SCADA等智能化系统逐渐成为工厂管理的标配,于是数据采集与维护也逐渐成为了工厂工作的重点,本人把工作中学习的项目分享给大家,希望能抛砖引玉,得到大家的指点和帮助!
项目预览与概述:

预览

电脑测试预览

手机测试预览

设计思路

概述
项目分为3个部分,硬件基础(数据收集),数据采集上传,信息展示(微信小程序)
一.硬件基础 西门子S71500 PLC 
1.设备选型,组态
2.数据块结构设计
3.OPC UA服务开启
4.仿真环境搭建
二.数据采集上传 OPC客户端
1.OPC UA 通信连接
2.数据采集(采用订阅方式)
3.数据处理或上传微信云数据库
三.信息展示(微信小程序)
1.选择云开发,云模板
2.修改界面
2.修改云函数和数据展示逻辑

 项目实施:
一.硬件基础 西门子S71500 PLC 
1.设备选型,组态


2.数据块结构设计

为了方便数据数据采集,数据块一定要设计合理,尽量模块化


3.OPC UA服务开启

西门子1500PLC配置OPC相当简单,选择好授权激活OPC服务器功能即可,具体几个容易出错的小细节见图片

尽量启用访客认证,这样方便测试


4.仿真环境搭建

我为了方便测试,电脑上安装了VM虚拟机,虚拟机里安装博途V15.1和模拟器S7-PLCSIM Advanced V3.0,如果大家也和我一样那么要注意IP设置,否则OPC客户端在本机无法采集数据,详细见下图

 仿真时一定要选上支持仿真的功能,许可证类型要选上

 二.数据采集上传 OPC客户端
1.OPC UA 通信连接

1.引用OPC官方的Opc.Ua.Client.dll,Opc.Ua.Core.dll

2.引用开源的OPCHelper(编译后引用)

网上搜索的帮助类,自己修改了一下,具体代码如图

OPC UA详细使用方法见下面这位大牛的文章

牛奶咖啡13

C#使用OpcUaHelper开源库开发客户端实现读取、订阅OPC UA服务器节点信息_牛奶咖啡13的博客-CSDN博客_c# opc ua客户端

//声明对象
private OpcHleperTest opctest;
//实例化对象
opctest = new OpcHleperTest();

//连接

try
            {
                //判断连接状态后连接
                if (!opctest.ConnectStatus)
            {
//注意连接地址
                opctest.OpenConnectOfAnonymous("opc.tcp://192.168.40.8:4840");
            }
            //判断连接状态后按钮改变颜色
            if (opctest.ConnectStatus)
            {
                    button1.BackColor = Color.YellowGreen;
                    button1.Text = "已连接";
                    label9.BackColor = Color.Yellow;
            }

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }

2.数据采集(采用订阅方式),数据处理

订阅

//定义需要订阅的数据
            string str1 = "ns=3;s=\"opctest\".\"station1\".\"equipment\".\"speed\"";
            string str2 = "ns=3;s=\"opctest\".\"station1\".\"equipment\".\"state\"";
            string str3 = "ns=3;s=\"opctest\".\"station1\".\"operator\".\"name\"";
            string str4 = "ns=3;s=\"opctest\".\"station1\".\"operator\".\"state\"";
//加入数组
            string[] nolds = new string[] { str1, str2 , str3 , str4 };
//批量订阅
            opctest.BatchNodeIdDatasSubscription("monitor", nolds, SubCallback);


3.数据处理或上传微信云数据库

//数据订阅的回调函数
        private void SubCallback(string key, MonitoredItem monitoredItem, MonitoredItemNotificationEventArgs args)
        {
            if (InvokeRequired)
            {
                Invoke(new Action<string, MonitoredItem, MonitoredItemNotificationEventArgs>(SubCallback), key, monitoredItem, args);
                return;
            }

            // 如果有多个的订阅值都关联了当前的方法,可以通过key和monitoredItem来区分
            MonitoredItemNotification notification = args.NotificationValue as MonitoredItemNotification;
            if (notification != null)
            {
                //运行速度
                if(monitoredItem.StartNodeId.ToString()== "ns=3;s=\"opctest\".\"station1\".\"equipment\".\"speed\"")
                {
//取出订阅返回的值
                    textBox2.Text = notification.Value.WrappedValue.Value.ToString();
//数据上传到微信云数据库
                    UpData("Speed_Station1", textBox2.Text);
                }
                //设备状态
                if (monitoredItem.StartNodeId.ToString() == "ns=3;s=\"opctest\".\"station1\".\"equipment\".\"state\"")
                {
//判断取回的值
                    if(notification.Value.WrappedValue.Value.ToString()=="0")
                    {
//改变标签的颜色
                        label6.BackColor = Color.Yellow;
                        label5.BackColor = Control.DefaultBackColor;
                        label7.BackColor = Control.DefaultBackColor;
//数据上传到微信云数据库
                        UpData("State_Station1", "0");
                    }
                    if (notification.Value.WrappedValue.Value.ToString() == "1")
                    {
                        label5.BackColor = Color.YellowGreen;
                        label6.BackColor = Control.DefaultBackColor;
                        label7.BackColor = Control.DefaultBackColor;
                        UpData("State_Station1", "1");
                    }
                    if (notification.Value.WrappedValue.Value.ToString() == "3")
                    {
                        label7.BackColor = Color.Red;
                        label5.BackColor = Control.DefaultBackColor;
                        label6.BackColor = Control.DefaultBackColor;
                        UpData("State_Station1", "3");
                    }
                }
                //工号
                if (monitoredItem.StartNodeId.ToString() == "ns=3;s=\"opctest\".\"station1\".\"operator\".\"name\"")
                {
                    textBox1.Text = notification.Value.WrappedValue.Value.ToString();
                    UpData("Code_OP", textBox1.Text);
                }
                //人员状态
                if (monitoredItem.StartNodeId.ToString() == "ns=3;s=\"opctest\".\"station1\".\"operator\".\"state\"")
                {
                    if (notification.Value.WrappedValue.Value.ToString()== "True")
                    {
                        label3.BackColor = Color.YellowGreen;
                        label8.BackColor = Control.DefaultBackColor;
                        UpData("State_OP", "true");
                    }
                    if (notification.Value.WrappedValue.Value.ToString() == "False")
                    {
                        label8.BackColor = Color.Red;
                        label3.BackColor = Control.DefaultBackColor;
                        UpData("State_OP", "false");
                    }
                }
            }

        }

3.微信云数据库修改

获取修改数据库的官方获取测试地址

微信公众平台接口调试工具

// 通过Get请求获取access_token
            HttpWebResponse httpWebResponse = GetRequest("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="你的appid"&secret="你的secret"");
            string resultJson = HttpWebResponseToString(httpWebResponse);
            var resultObj = DesAnonymousType(resultJson, new { access_token = "", expires_in = "" });
            return resultObj.access_token;

 修改微信云数据库

​
​
 string accessToken = GetAccessToken();
            string accessTokenqueryString = $"{{\"env\":\"你的环境名称\", \"query\": \"db.collection(\\\"你的数据库名\\\").doc(\\\"你的数据库ID\\\")" + ".update({data:" + "{" + name + ":" + value + "}})\"}";
            HttpWebResponse httpWebResponse = PostRequest("https://api.weixin.qq.com/tcb/databaseupdate?access_token=" + accessToken, accessTokenqueryString);
            string data = HttpWebResponseToString(httpWebResponse);
            return data;

​

​

全部代码

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Opc.Ua;
using Opc.Ua.Client;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace SimChart
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            //实例化对象
            opctest = new OpcHleperTest();
        }
        //声明对象
        private OpcHleperTest opctest;
        private void Button1_Click(object sender, EventArgs e)
        {
            //云数据库的accessToken
            accessToken = GetAccessToken();
            try
            {
                //判断连接状态后连接
                if (!opctest.ConnectStatus)
            {
                opctest.OpenConnectOfAnonymous("opc.tcp://192.168.40.8:4840");
            }
            //判断连接状态后按钮改变颜色
            if (opctest.ConnectStatus)
            {
                    button1.BackColor = Color.YellowGreen;
                    button1.Text = "已连接";
                    label9.BackColor = Color.Yellow;
            }
            string str1 = "ns=3;s=\"opctest\".\"station1\".\"equipment\".\"speed\"";
            string str2 = "ns=3;s=\"opctest\".\"station1\".\"equipment\".\"state\"";
            string str3 = "ns=3;s=\"opctest\".\"station1\".\"operator\".\"name\"";
            string str4 = "ns=3;s=\"opctest\".\"station1\".\"operator\".\"state\"";
            string[] nolds = new string[] { str1, str2 , str3 , str4 };
            opctest.BatchNodeIdDatasSubscription("monitor", nolds, SubCallback);
            //opctest.SingleNodeIdDatasSubscription("opctest888", str1, SubCallback2);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
        //单节点数据订阅的回调函数
        private void SubCallback2(string key, MonitoredItem monitoredItem, MonitoredItemNotificationEventArgs args)
        {
            if (InvokeRequired)
            {
                Invoke(new Action<string, MonitoredItem, MonitoredItemNotificationEventArgs>(SubCallback2), key, monitoredItem, args);
                return;
            }

            // 如果有多个的订阅值都关联了当前的方法,可以通过key和monitoredItem来区分
            MonitoredItemNotification notification = args.NotificationValue as MonitoredItemNotification;
            if (notification != null)
            {
                textBox1.Text = notification.Value.WrappedValue.Value.ToString();
            }

        }
        //数据订阅的回调函数
        private void SubCallback(string key, MonitoredItem monitoredItem, MonitoredItemNotificationEventArgs args)
        {
            if (InvokeRequired)
            {
                Invoke(new Action<string, MonitoredItem, MonitoredItemNotificationEventArgs>(SubCallback), key, monitoredItem, args);
                return;
            }

            // 如果有多个的订阅值都关联了当前的方法,可以通过key和monitoredItem来区分
            MonitoredItemNotification notification = args.NotificationValue as MonitoredItemNotification;
            if (notification != null)
            {
                //运行速度
                if(monitoredItem.StartNodeId.ToString()== "ns=3;s=\"opctest\".\"station1\".\"equipment\".\"speed\"")
                {
                    textBox2.Text = notification.Value.WrappedValue.Value.ToString();
                    UpData("Speed_Station1", textBox2.Text);
                }
                //设备状态
                if (monitoredItem.StartNodeId.ToString() == "ns=3;s=\"opctest\".\"station1\".\"equipment\".\"state\"")
                {
                    if(notification.Value.WrappedValue.Value.ToString()=="0")
                    {
                        label6.BackColor = Color.Yellow;
                        label5.BackColor = Control.DefaultBackColor;
                        label7.BackColor = Control.DefaultBackColor;
                        UpData("State_Station1", "0");
                    }
                    if (notification.Value.WrappedValue.Value.ToString() == "1")
                    {
                        label5.BackColor = Color.YellowGreen;
                        label6.BackColor = Control.DefaultBackColor;
                        label7.BackColor = Control.DefaultBackColor;
                        UpData("State_Station1", "1");
                    }
                    if (notification.Value.WrappedValue.Value.ToString() == "3")
                    {
                        label7.BackColor = Color.Red;
                        label5.BackColor = Control.DefaultBackColor;
                        label6.BackColor = Control.DefaultBackColor;
                        UpData("State_Station1", "3");
                    }
                }
                //工号
                if (monitoredItem.StartNodeId.ToString() == "ns=3;s=\"opctest\".\"station1\".\"operator\".\"name\"")
                {
                    textBox1.Text = notification.Value.WrappedValue.Value.ToString();
                    UpData("Code_OP", textBox1.Text);
                }
                //人员状态
                if (monitoredItem.StartNodeId.ToString() == "ns=3;s=\"opctest\".\"station1\".\"operator\".\"state\"")
                {
                    if (notification.Value.WrappedValue.Value.ToString()== "True")
                    {
                        label3.BackColor = Color.YellowGreen;
                        label8.BackColor = Control.DefaultBackColor;
                        UpData("State_OP", "true");
                    }
                    if (notification.Value.WrappedValue.Value.ToString() == "False")
                    {
                        label8.BackColor = Color.Red;
                        label3.BackColor = Control.DefaultBackColor;
                        UpData("State_OP", "false");
                    }
                }
            }

        }
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            //关闭连接
            opctest.CloseConnect();
        }
        
        ///云数据库相关
        
        ///
        /// <summary>
        /// 发送http Get请求
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        public static HttpWebResponse GetRequest(string url)
        {
            HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
            request.Method = "GET";
            request.ContentType = "application/x-www-form-urlencoded";//链接类型
            return request.GetResponse() as HttpWebResponse;
        }

        /// <summary>
        /// 发送http Post请求
        /// </summary>
        /// <returns></returns>
        public static HttpWebResponse PostRequest(string url, string messsage)
        {
            byte[] byteData = Encoding.UTF8.GetBytes(messsage);
            HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);
            webRequest.Method = "POST";
            webRequest.ContentType = "application/json;charset=UTF-8";
            webRequest.ContentLength = byteData.Length;
            using (Stream stream = webRequest.GetRequestStream())
            {
                stream.Write(byteData, 0, byteData.Length);
            }
            HttpWebResponse response = (HttpWebResponse)webRequest.GetResponse();
            return response;
        }

        /// <summary>
        /// 从HttpWebResponse对象中提取响应的数据转换为字符串
        /// </summary>
        /// <param name="webresponse"></param>
        /// <returns></returns>
        public static string HttpWebResponseToString(HttpWebResponse webresponse)
        {
            using (Stream s = webresponse.GetResponseStream())
            {
                StreamReader reader = new StreamReader(s, Encoding.UTF8);
                return reader.ReadToEnd();
            }
        }

        /// <summary>
        /// Json字符串转为匿名对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="json"></param>
        /// <param name="anonymousTypeObject"></param>
        /// <returns></returns>
        public static T DesAnonymousType<T>(string json, T anonymousTypeObject)
        {
            return JsonConvert.DeserializeAnonymousType(json, anonymousTypeObject);
        }
        /// <summary>
        /// 获取access_token
        /// </summary>
        /// <returns></returns>
        public static string GetAccessToken()
        {
            // 通过Get请求获取access_token
            HttpWebResponse httpWebResponse = GetRequest("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=wx017496cac8389210&secret=51c000bc2fa6d32fa8969e9cb8f71072");
            string resultJson = HttpWebResponseToString(httpWebResponse);
            var resultObj = DesAnonymousType(resultJson, new { access_token = "", expires_in = "" });
            return resultObj.access_token;
        }

        /// <summary>
        ///  查询数据
        /// </summary>
        /// <param name="queryString">形如: $"{{\"env\":\"小程序环境id\", \"query\": \"db.collecti(\\\"数据集合名称\\\").where({{集合中字段:\\\"集合中字段值\\\"}}).limit(10).get()\"}}"</param>
        /// <returns></returns>
        //public static string GetData(string queryString)
        public static string GetData()
        {
            string accessToken = GetAccessToken();
            string accessTokenqueryString = $"{{\"env\":\"zunzhi-5gthrfdrd0504463\", \"query\": \"db.collection(\\\"Test\\\").where({{_id:\\\"TestByClient\\\"}}).limit(10).get()\"}}";
            HttpWebResponse httpWebResponse = PostRequest("https://api.weixin.qq.com/tcb/databasequery?access_token=" + accessToken, accessTokenqueryString);
            string data = HttpWebResponseToString(httpWebResponse);
            return data;
        }
       static string accessToken = "";
        /// <summary>
        ///  更新数据
        /// </summary>
        /// <param name="queryString">形如: $"{{\"env\":\"小程序环境id\", \"query\": \"db.collecti(\\\"数据集合名称\\\").where({{集合中字段:\\\"集合中字段值\\\"}}).update({data:{集合中字段:\\\"集合中字段值\\\"})"</param>
        /// <returns></returns>
        //public static string GetData(string queryString)
        public static string UpData(string name, string value)
        {
            //string accessToken = GetAccessToken();
            string accessTokenqueryString = $"{{\"env\":\"zunzhi-5gthrfdrd0504463\", \"query\": \"db.collection(\\\"Test\\\").doc(\\\"TestByClient\\\")" + ".update({data:" + "{" + name + ":" + value + "}})\"}";
            HttpWebResponse httpWebResponse = PostRequest("https://api.weixin.qq.com/tcb/databaseupdate?access_token=" + accessToken, accessTokenqueryString);
            string data = HttpWebResponseToString(httpWebResponse);
            return data;
        }

        /// <summary>
        /// 通过FileId获取文件下载URL
        /// </summary>
        /// <param name="queryString">形如:$"{{\"env\": \"环境ID\",\"file_list\": [{{\"fileid\":文件ID\",\"max_age\":7200 }}]}}"</param>
        /// <returns></returns>
        public static string GetDownFileUrl(string queryString)
        {
            string accessToken = GetAccessToken();
            string url = $"https://api.weixin.qq.com/tcb/batchdownloadfile?access_token={accessToken}";
            HttpWebResponse httpWebResponse = PostRequest(url, queryString);
            string downFileUrl = HttpWebResponseToString(httpWebResponse);
            return downFileUrl;
        }
        //提取数据
        public static string GetValue(string JsonString, string Jsonvalue)
        {
            JObject JsonTemp = JObject.Parse(JsonString);
            string str1 = JsonTemp["data"].ToString().Replace("[", "").Replace("]", "").Trim();
            str1 = str1.Substring(1, str1.Length - 2).Replace(@"\", "");
            JObject JsonTemp2 = JObject.Parse(str1);
            string str2 = JsonTemp2[Jsonvalue].ToString();
            return str2;
        }
    }
}

 正常后返回的数据见下图

三.信息展示(微信小程序)

1.选择云开发,云模板

打开微信的官方开发软件,建立项目,选择云开发,选择官方的云模板

 2.简单修改一下界面

把模板中不需要的注释掉,加入自己的代码

<view class="title">XX车间状态</view>

  <view class="top_tip">努力工作!好好学习!</view>
  <view class="app">
    员工
    <view class="horizontal">
      <view style="color: lightsalmon;">员工工号</view>
      <view style="border-style:solid; border-color: darkorchid; height: 38px;width: 200px;color: olivedrab;text-align: center;">{{record[0]["Code_OP"]}}</view>
    </view>
    <view class="horizontal">
      <text wx:if="{{record[0]['State_OP']}}" style="border-style:solid;border-color: turquoise; background-color: rgb(30, 235, 23);">在岗</text>
      <text wx:else="" style="border-style:solid;border-color: turquoise; background-color: slategray;">在岗</text>
      <text wx:if="{{!record[0]['State_OP']}}"style="border-style:solid;border-color: turquoise; background-color:red;">离岗</text>
      <text wx:else="" style="border-style:solid;border-color: turquoise; background-color: slategray;">离岗</text>
    </view>
  </view>
  <view class="app">
    设备
    <view class="horizontal">
      <view style="color: lightsalmon;">运行速度</view>
      <view style="border-style:solid; border-color: darkorchid; height: 38px;width: 200px;color: olivedrab;text-align: center;">{{record[0]["Speed_Station1"]}}</view>
    </view>
    <view class="horizontal">
      <text wx:if="{{record[0]['State_Station1']==1}}" style="border-style:solid;border-color: turquoise; background-color: rgb(30, 235, 91);">运行</text>
      <text wx:else="" style="border-style:solid;border-color: turquoise; background-color: slategray;">运行</text>
      <text wx:if="{{record[0]['State_Station1']==0}}" style="border-style:solid;border-color: turquoise; background-color: yellow;">停止</text>
      <text wx:else="" style="border-style:solid;border-color: turquoise; background-color: slategray;">停止</text>
      <text wx:if="{{record[0]['State_Station1']==3}}" style="border-style:solid;border-color: turquoise; background-color:red;">故障</text>
      <text wx:else="" style="border-style:solid;border-color: turquoise; background-color: slategray;">故障</text>
    </view>
  </view>
  <button style="border-style: solid; border-color: springgreen;background-color: palegreen;margin-top: 30px;" bindtap="getRecord">刷新</button>

 3..修改云函数和数据展示逻辑

添加云数据库信息

修改微信云函数,修改后一定上传部署

在页面的js文件中加入查询云数据库的方法

//查询数据
getRecord() {
  wx.showLoading({
    title: '',
  });
 wx.cloud.callFunction({
    name: 'quickstartFunctions',
    config: {
      env: this.data.envId
    },
    data: {
//注意这个命令,不要选错
      type: 'selectRecord'
    }
  }).then((resp) => {
    this.setData({
      haveGetRecord: true,
      record: resp.result.data
    });
   wx.hideLoading();
 }).catch((e) => {
    console.log(e);
    this.setData({
      showUploadTip: true
    });
   wx.hideLoading();
 });
},

 修改后保存编译,模拟器就会显示查询的结果,是不是很惊喜?整个项目比较简单,稍微有些编程知识即可入手

我在页面中加入了定时器可以实现数据实时更新,但很快就把我的数据库测试次数用完了,所以就注释掉了,大家打开注释用定时器刷新页面时一定要注意,每天的次数用完微信官方就不允许访问数据库了!页面写满了,无法再写了,代码见附件吧,我已分类打包,完整上传!最后谢谢大家的观看,大家互相交流,共同进步,谢谢!

项目资源下载

工业4.0智能工厂简单学习项目-C#文档类资源-CSDN下载

有关工业4.0 智能工厂简单学习项目的更多相关文章

  1. ruby-on-rails - Railstutorial : db:populate vs. 工厂女孩 - 2

    在railstutorial中,作者为什么选择使用这个(代码list10.25):http://ruby.railstutorial.org/chapters/updating-showing-and-deleting-usersnamespace:dbdodesc"Filldatabasewithsampledata"task:populate=>:environmentdoRake::Task['db:reset'].invokeUser.create!(:name=>"ExampleUser",:email=>"example@railstutorial.org",:passwo

  2. ruby - 如何在 buildr 项目中使用 Ruby 代码? - 2

    如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby​​

  3. ruby-on-rails - 项目升级后 Pow 不会更改 ruby​​ 版本 - 2

    我在我的Rails项目中使用Pow和powifygem。现在我尝试升级我的ruby​​版本(从1.9.3到2.0.0,我使用RVM)当我切换ruby​​版本、安装所有gem依赖项时,我通过运行railss并访问localhost:3000确保该应用程序正常运行以前,我通过使用pow访问http://my_app.dev来浏览我的应用程序。升级后,由于错误Bundler::RubyVersionMismatch:YourRubyversionis1.9.3,butyourGemfilespecified2.0.0,此url不起作用我尝试过的:重新创建pow应用程序重启pow服务器更新战俘

  4. ruby-on-rails - 新 Rails 项目 : 'bundle install' can't install rails in gemfile - 2

    我已经像这样安装了一个新的Rails项目:$railsnewsite它执行并到达:bundleinstall但是当它似乎尝试安装依赖项时我得到了这个错误Gem::Ext::BuildError:ERROR:Failedtobuildgemnativeextension./System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/rubyextconf.rbcheckingforlibkern/OSAtomic.h...yescreatingMakefilemake"DESTDIR="cleanmake"DESTDIR="

  5. ruby - 简单获取法拉第超时 - 2

    有没有办法在这个简单的get方法中添加超时选项?我正在使用法拉第3.3。Faraday.get(url)四处寻找,我只能先发起连接后应用超时选项,然后应用超时选项。或者有什么简单的方法?这就是我现在正在做的:conn=Faraday.newresponse=conn.getdo|req|req.urlurlreq.options.timeout=2#2secondsend 最佳答案 试试这个:conn=Faraday.newdo|conn|conn.options.timeout=20endresponse=conn.get(url

  6. ruby - 用 Ruby 编写一个简单的网络服务器 - 2

    我想在Ruby中创建一个用于开发目的的极其简单的Web服务器(不,不想使用现成的解决方案)。代码如下:#!/usr/bin/rubyrequire'socket'server=TCPServer.new('127.0.0.1',8080)whileconnection=server.acceptheaders=[]length=0whileline=connection.getsheaders想法是从命令行运行这个脚本,提供另一个脚本,它将在其标准输入上获取请求,并在其标准输出上返回完整的响应。到目前为止一切顺利,但事实证明这真的很脆弱,因为它在第二个请求上中断并出现错误:/usr/b

  7. Ruby 从大范围中获取第 n 个项目 - 2

    假设我有这个范围:("aaaaa".."zzzzz")如何在不事先/每次生成整个项目的情况下从范围中获取第N个项目? 最佳答案 一种快速简便的方法:("aaaaa".."zzzzz").first(42).last#==>"aaabp"如果出于某种原因你不得不一遍又一遍地这样做,或者如果你需要避免为前N个元素构建中间数组,你可以这样写:moduleEnumerabledefskip(n)returnto_enum:skip,nunlessblock_given?each_with_indexdo|item,index|yieldit

  8. ruby-on-rails - 简单的 Ruby on Rails 问题——如何将评论附加到用户和文章? - 2

    我意识到这可能是一个非常基本的问题,但我现在已经花了几天时间回过头来解决这个问题,但出于某种原因,Google就是没有帮助我。(我认为部分问题在于我是一个初学者,我不知道该问什么......)我也看过O'Reilly的RubyCookbook和RailsAPI,但我仍然停留在这个问题上.我找到了一些关于多态关系的信息,但它似乎不是我需要的(尽管如果我错了请告诉我)。我正在尝试调整MichaelHartl'stutorial创建一个包含用户、文章和评论的博客应用程序(不使用脚手架)。我希望评论既属于用户又属于文章。我的主要问题是:我不知道如何将当前文章的ID放入评论Controller。

  9. ruby - 使用 Ruby 通过 Outlook 发送消息的最简单方法是什么? - 2

    我的工作要求我为某些测试自动生成电子邮件。我一直在四处寻找,但未能找到可以快速实现的合理解决方案。它需要在outlook而不是其他邮件服务器中,因为我们有一些奇怪的身份验证规则,我们需要保存草稿而不是仅仅发送邮件的选项。显然win32ole可以做到这一点,但我找不到任何相当简单的例子。 最佳答案 假设存储了Outlook凭据并且您设置为自动登录到Outlook,WIN32OLE可以很好地完成此操作:require'win32ole'outlook=WIN32OLE.new('Outlook.Application')message=

  10. postman——集合——执行集合——测试脚本——pm对象简单示例02 - 2

    //1.验证返回状态码是否是200pm.test("Statuscodeis200",function(){pm.response.to.have.status(200);});//2.验证返回body内是否含有某个值pm.test("Bodymatchesstring",function(){pm.expect(pm.response.text()).to.include("string_you_want_to_search");});//3.验证某个返回值是否是100pm.test("Yourtestname",function(){varjsonData=pm.response.json

随机推荐