newoneday 发布的文章

#region 日志处理
class ColoredFormatter(logging.Formatter):
    # 定义颜色代码
    COLORS = {
        'DEBUG': '\033[94m',  # 蓝色
        'INFO': '\033[92m',   # 绿色
        'WARNING': '\033[93m',  # 黄色
        'ERROR': '\033[91m',   # 红色
        'CRITICAL': '\033[41m', # 红色背景
    }
    RESET = '\033[0m'  # 重置颜色

    def format(self, record):
        # 根据日志级别选择颜色
        color = self.COLORS.get(record.levelname, self.RESET)
        return color + super().format(record) + self.RESET        
        #return  super().format(record).replace(record.getMessage(), f"{color}{record.getMessage()}{self.RESET}")    
        
#设置logging 输出到控制台
logger=logging.getLogger()
handler=logging.StreamHandler()
handler.setFormatter(ColoredFormatter(fmt='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',datefmt='%Y-%m-%d %H:%M:%S'))
logger.addHandler(handler)
logger.setLevel(logging.DEBUG)
#endregion

PLC常见的数据类型对应表:

PLC数据类型C#数据类型备注
BOOLbool布尔类型,表示真或假
BYTEbyte8位无符号整数
WORDushort16位无符号整数
DWORDuint32位无符号整数
LWORDulong64位无符号整数
SINTsbyte8位有符号整数
INTshort16位有符号整数
DINTint32位有符号整数
LINTlong64位有符号整数
USINTbyte8位无符号整数,与BYTE相同
UINTushort16位无符号整数,与WORD相同
UDINTuint32位无符号整数,与DWORD相同
ULINTulong64位无符号整数,与LWORD相同
REALfloat32位浮点数
LREALdouble64位浮点数
STRINGstring字符串
TIMETimeSpan表示时间间隔
DATEDateTime表示日期
TIME_OF_DAYDateTime表示一天中的时间
DATE_AND_TIMEDateTime表示日期和时间

ffmpeg -i out.wav -f s16le -ar 8000 -ac 1 -acodec pcm_s16le out.pcm
ffmpeg -i a.mp3 -f s16le -ar 8000 -ac 1 -acodec pcm_s16le a.pcm
参数说明
-ia.mp3源文件
-fs16le强制文件格式
-ar8000采样率
-ac1单声道
-acodecpcm_s16le编码器

在使用海康摄像头输出音频,选择pcm文件进行播放,如果摄像头解码器是G711 对应的pcm文件是采样率是8000,编码器 pcm_s16le

  public static object GetPropertyValue<TObject>(this PropertyInfo propertyInfo, TObject obj) where TObject : class
    {
        if (propertyInfo == null)
        {
            LoggerHandler.OnLogError("GetPropertyValue", new ArgumentNullException("propertyInfo null"));
            throw new ArgumentNullException("propertyInfo");
        }

        ParameterExpression parameterExpression = Expression.Parameter(typeof(TObject));
        return Expression.Lambda<Func<TObject, object>>(Expression.Convert(Expression.Property(Expression.Convert(parameterExpression, obj.GetType()), propertyInfo), typeof(object)), new ParameterExpression[1] { parameterExpression }).Compile()(obj);
    }
 public static void SetPropertyValue<TObject, TValue>(this PropertyInfo propertyInfo, TObject obj, TValue value)
    {
        if (propertyInfo == null)
        {
            LoggerHandler.OnLogError("SetPropertyValue", new ArgumentNullException("Property null"));
            throw new ArgumentNullException("propertyInfo");
        }

        if (propertyInfo.GetSetMethod() == null)
        {
            LoggerHandler.OnLogError("SetPropertyValue", new InvalidOperationException("Property does not have a setter"));
            throw new InvalidOperationException("Property does not have a setter");
        }

        ParameterExpression parameterExpression = Expression.Parameter(typeof(TObject));
        MemberExpression left = Expression.Property(Expression.Convert(parameterExpression, obj.GetType()), propertyInfo);
        ParameterExpression parameterExpression2 = Expression.Parameter(typeof(TValue));
        UnaryExpression right = Expression.Convert(parameterExpression2, propertyInfo.PropertyType);
        Expression.Lambda<Action<TObject, TValue>>(Expression.Assign(left, right), new ParameterExpression[2] { parameterExpression, parameterExpression2 }).Compile()(obj, value);
    }

线程(Threads)和协程(Coroutines)都是用于处理并发任务的编程概念,但它们有一些重要的区别。

线程:

  1. 线程是操作系统调度的最小执行单元。多个线程可以在同一进程内并发执行,共享进程的资源,如内存空间、文件描述符等。
  2. 线程之间的切换由操作系统负责,这个切换过程需要保存和恢复线程的上下文,因此线程切换的开销较大。
  3. 线程是抢占式的,意味着一个线程可以强制剥夺其他线程的执行权。
  4. 多线程编程需要考虑同步和资源竞争问题,比较容易出现并发错误,如死锁、竞态条件等。

协程:

  1. 协程是一种用户态的轻量级线程,也称为“微线程”或“纤程”。
  2. 协程由程序员显式地控制调度,可以通过主动让出执行权或者被其他协程显式调度来切换。
  3. 协程的切换开销相对较小,因为切换是在用户态进行,不需要操作系统的介入。
  4. 协程通常是合作式的,一个协程执行时需要主动让出执行权才能切换到其他协程。

主要区别:

  1. 调度方式:线程由操作系统内核调度,协程由用户程序自行调度。
  2. 切换开销:线程切换的开销较大,协程切换的开销相对较小。
  3. 合作与抢占:线程是抢占式的,而协程是合作式的。
  4. 编程模型:多线程编程需要考虑同步和竞争问题,而协程更加轻量,不需要显式的同步操作,更容易编写和维护。

协程在某些场景下能够提供更高的性能和更简洁的代码,尤其是在I/O密集型任务(如网络通信、文件读写等)中。然而,线程在处理CPU密集型任务时可能更具优势,因为它们可以利用多核处理器的并行性。不过,要注意不同编程语言和框架对于协程和线程的支持程度可能有所不同,有些语言可能提供了更便捷的协程支持,而有些语言可能更擅长处理线程。