1. Обязательно представиться на русском языке кириллицей (заполнить поле "Имя").
  2. Фиктивные имена мы не приветствуем. Ивановых и Пупкиных здесь уже достаточно.
  3. Не писать свой вопрос в первую попавшуюся тему - вместо этого создать новую тему.
  4. За поиск, предложение и обсуждение пиратского ПО и средств взлома - бан без предупреждения.
  5. Рекламу и частные объявления "куплю/продам/есть халтура" мы не размещаем ни на каких условиях.
  6. Перед тем как что-то написать - читать здесь и здесь, а студентам - обязательно здесь.
  7. Не надо писать в ЛС администраторам свои технические вопросы. Администраторы форума отлично знают как работает форум, а не все-все контроллеры, о которых тут пишут.

Сброс значений в SQL по времени

Ответить

Автор темы
stesl
эксперт
эксперт
Сообщения: 1008
Зарегистрирован: 31 мар 2018, 12:05
Имя: Вячеслав
Благодарил (а): 94 раза
Поблагодарили: 136 раз

Сброс значений в SQL по времени

Сообщение stesl »

Всем привет!
Продолжаю красться по пути "хрен его знает"

Как то знаний по VB и его применению в WinCC не прибавляется. Все методом тыка.
Задача: Скинуть значения тэгов в базу (пока Access хотя бы, ибо с MS SQL еще не начинал даже)

Код: Выделить всё

Option Explicit
Function action
  Dim objConnection
  Set objConnection = CreateObject("ADODB.Connection")

  Dim strConnectionString
  Dim databasefile
  Dim strSQL

  databasefile = "C:\Users\SCADA-Ingeniring\Documents\DB1.accdb"
  
strConnectionString = "provider=Microsoft.ACE.OLEDB.12.0; Data Source=" + databasefile
'strConnectionString = "Driver={Microsoft Access Driver (*.mdb, *.accdb)};DBQ=C:\Users\SCADA-Ingeniring\Documents\DB1.accdb;Uid=Admin;Pwd=;"

  objConnection.ConnectionTimeout = 600
  objConnection.Open strConnectionString

'  	strSQL = "insert into Tab1 (Pos, Dat) values ('Tag1', 2.67)"
	strSQL = "UPDATE Tab1 SET Tab1.Dat = HMIRuntime.Tags("Tag1").Read WHERE ((Tab1!Pos)='L_I_SPR')"

  objConnection.Execute strSQL
End Function
Это создано в разделе Action c нужным триггером. Запинается на моменте HMIRuntime.Tags("Tag1").Read мол не могу такого. Из этого Action нельзя теги получать? Уж извините, пока далеко не все понимаю.
Закомментированные команды (обращение к Access ч/з драйвер и вставка в таблицу БД) исполняются. Вопрос только в том, как тег выдернуть (значение).

И еще вопросик, если позволите. Теги структурные и скидывать мне надо *.AVERAGE. К примеру - Tag1.AVERAGE. Если не трудно, накидайте скриптик как сделать выборку по тегам и как использовать имя найденного тэга (ту часть что перед точкой) для адресации к заголовку таблицы БД. Сам синтаксис. Через него не могу пробиться. Впрочем как и со всяким новым языком.

Andreywys
освоился
освоился
Сообщения: 290
Зарегистрирован: 15 сен 2016, 18:47
Имя: Андрей
Страна: Россия
город/регион: Вологда
Благодарил (а): 19 раз
Поблагодарили: 76 раз

Сброс значений в SQL по времени

Сообщение Andreywys »

Недавно скрипт выкладывал viewtopic.php?f=157&t=12222&p=98546#p98546 , посмотрите.

Автор темы
stesl
эксперт
эксперт
Сообщения: 1008
Зарегистрирован: 31 мар 2018, 12:05
Имя: Вячеслав
Благодарил (а): 94 раза
Поблагодарили: 136 раз

Сброс значений в SQL по времени

Сообщение stesl »

Andreywys писал(а): 14 июн 2019, 12:53 Недавно скрипт выкладывал viewtopic.php?f=157&t=12222&p=98546#p98546 , посмотрите.
Спасибо. Это наверно скорее ответ на вторую часть вопроса. Но в целом это скрипт по событию, как я понимаю? Мой Action работает по времени и было бы здорово дополнить его Вашими строчками, с созданием множества (а я так понимаю HMIRuntime.Tags.CreateTagSet ибо знаю на оч. хорошо только Паскаль:), но сможет ли он дотянуться из скрипта в разделе Action до тэгов?

Это пока основной вопрос. В синтаксисе я уверен, но вижу такое
Изображение

winb
освоился
освоился
Сообщения: 248
Зарегистрирован: 31 янв 2017, 08:44
Имя: Маркушин Андрей Геннадьевич
Страна: Россия
город/регион: Нижегородская обл., Выкса
Благодарил (а): 19 раз
Поблагодарили: 64 раза

Сброс значений в SQL по времени

Сообщение winb »

strSQL - это строка команды на изменение данных, которую вы посылаете в СУБД (Access там или MSSQL - в принципе без разницы). СУБД не знает, что такое "HMIRuntime.Tags("Tag1").Read". Пробуйте собрать строку на стороне скрипта (например - strSQL = "UPDATE Tab1 SET Tab1.Dat = " + СStr(HMIRuntime.Tags("Tag1").Read) + " WHERE ((Tab1!Pos)='L_I_SPR')"), либо используйте параметры SQL-команды

Andreywys
освоился
освоился
Сообщения: 290
Зарегистрирован: 15 сен 2016, 18:47
Имя: Андрей
Страна: Россия
город/регион: Вологда
Благодарил (а): 19 раз
Поблагодарили: 76 раз

Сброс значений в SQL по времени

Сообщение Andreywys »

Скрипт по времени
Снимок.PNG
У вас нет необходимых прав для просмотра вложений в этом сообщении.

Автор темы
stesl
эксперт
эксперт
Сообщения: 1008
Зарегистрирован: 31 мар 2018, 12:05
Имя: Вячеслав
Благодарил (а): 94 раза
Поблагодарили: 136 раз

Сброс значений в SQL по времени

Сообщение stesl »

Andreywys писал(а): 14 июн 2019, 14:20 Скрипт по времени
Снимок.PNG
Мне портала для полного кайфа не хватает :crazy0to:
Изображение
Тут (WinCC 7.4) такого нет.
winb писал(а): 14 июн 2019, 14:18 strSQL - это строка команды на изменение данных, которую вы посылаете в СУБД (Access там или MSSQL - в принципе без разницы). СУБД не знает, что такое "HMIRuntime.Tags("Tag1").Read". Пробуйте собрать строку на стороне скрипта (например - strSQL = "UPDATE Tab1 SET Tab1.Dat = " + СStr(HMIRuntime.Tags("Tag1").Read) + " WHERE ((Tab1!Pos)='L_I_SPR')"), либо используйте параметры SQL-команды
Вроде понимаю. Вроде должно быть как то так

Код: Выделить всё

Option Explicit
Function action

Dim objConnection
Set objConnection = CreateObject("ADODB.Connection")
Dim strConnectionString
Dim databasefile
Dim strSQL
Dim L_I_PRREAL
Set L_I_PRREAL = HMIRuntime.Tags("L_I_PR.REAL")

databasefile = "C:\Users\SCADA-Ingeniring\Documents\DB1.accdb"
  
strConnectionString = "provider=Microsoft.ACE.OLEDB.12.0; Data Source=" + databasefile
'strConnectionString = "Driver={Microsoft Access Driver (*.mdb, *.accdb)};DBQ=C:\Users\SCADA-Ingeniring\Documents\DB1.accdb;Uid=Admin;Pwd=;"Dim L_I_PRREAL
objConnection.ConnectionTimeout = 600
objConnection.Open strConnectionString

'strSQL = "insert into Tab1 (Pos, Dat) values ('L_I_SPR', L_I_PRREAL)"
strSQL = "UPDATE Tab1 SET Tab1.Dat =" + L_I_PRREAL + "WHERE ((Tab1!Pos)='L_I_SPR')"

objConnection.Execute strSQL

End Function
Но наверняка что то с синтаксисом. И вот эти строки

Код: Выделить всё

Dim L_I_PRREAL
Set L_I_PRREAL = HMIRuntime.Tags("L_I_PR.REAL")
добавил Wizard. Read нету, что смущает. Но это потому что стоит оператор Set? Если я ручками добавляю Read, и оставляю в скрипте только эти 2 строчки, то и идет ругань как на моем скрине в пред топике.

Помогите побороть синтаксис.

А с Вашей строкой я что то вообще блужу. Как на Лиспе - одни скобкэ :roll:

PS Поменял строку

Код: Выделить всё

strSQL = "UPDATE Tab1 SET Tab1.Dat =" + CStr(L_I_PRREAL.Read) + "WHERE ((Tab1!Pos)='L_I_SPR')"
Теперь получаю ошибку - "Ошибка в синтаксисе Update". Но если я вместо этой переменной ставлю какое то значение (2.3 например)

Код: Выделить всё

strSQL = "UPDATE Tab1 SET Tab1.Dat =2.3 WHERE ((Tab1!Pos)='L_I_SPR')"
, то скрипт работает. Дак в чем ошибка?...

Отправлено спустя 52 минуты 39 секунд:
Это мука, а не работа )))
Путем тщательного мозгового штурма ответов обоих коллег - истина родилась

Код: Выделить всё

strSQL = "UPDATE Tab1 SET Tab1.Dat ='" + CStr(L_I_PRREAL.Read) + "' WHERE ((Tab1!Pos)='L_I_SPR')"
ОНО в одинарные кавычки должно быть заключено.

Ну кто нибудь... Ну чего нибудь на русском по VBS почитать - без всяких соплей типа для чайников, чисто столпы: синтаксис, преобразования, типы переменных и пр. В чем разница VBS и VBA и т.д.

Andreywys
освоился
освоился
Сообщения: 290
Зарегистрирован: 15 сен 2016, 18:47
Имя: Андрей
Страна: Россия
город/регион: Вологда
Благодарил (а): 19 раз
Поблагодарили: 76 раз

Сброс значений в SQL по времени

Сообщение Andreywys »

Мне портала для полного кайфа не хватает
Думаю, что в Simatic WinCC 7.4 тоже можно сделать.

Код: Выделить всё

Set L_I_PRREAL = HMIRuntime.Tags("L_I_PR.REAL")
String = L_I_PRREAL.Read
и

Код: Выделить всё

String = HMIRuntime.Tags("L_I_PR.REAL").Read
В первом случае вы создаете объект L_I_PRREAL. После чего дергаете его метод read. Метод возвращает строку, которую вы присваиваете переменной.
По сути, обе записи делают одно и тоже.


Читайте https://cache.industry.siemens.com/dl/f ... _en-US.pdf
Ищите в гугле учебник по vbs.

Автор темы
stesl
эксперт
эксперт
Сообщения: 1008
Зарегистрирован: 31 мар 2018, 12:05
Имя: Вячеслав
Благодарил (а): 94 раза
Поблагодарили: 136 раз

Сброс значений в SQL по времени

Сообщение stesl »

Ясно, ООП штучки :) Объекты, методы... Так комфортно было со своим Паскалем штанишки протирать...
Спасибо за, пусть и коротенькое, но объяснение чего то существенного.

PS "ОНО" думало это же Bacic мать его, чего там проще то :roll:

Отправлено спустя 15 минут 36 секунд:
И, кстати, при переходе на MS SQL выскочила другая проблема. Сама строка для SQL выглядит не в пример проще

Код: Выделить всё

strSQL = "UPDATE Tab1 SET Dat = 777.666 WHERE Pos='L_I_SVR'" '" & L_I_PRREAL.Read & "
И это работает. А вот

Код: Выделить всё

strSQL = "UPDATE Tab1 SET Dat =" & L_I_PRREAL.Read & "WHERE Pos='L_I_SVR' "
уже только в случае если тэг окажется 0 (ну может и другим целым числом, работаю с СИМ Степ 7, ибо Тег Симулятор WinCC написан какими то наркошами. И целое в СИМ Степ 7 поймать трудно). Причем независимо какой тип Dat я делаю в самой базе. В WinCC тег конечно float. Это аналоговый уровень, чтобы быть точнее.

Пока что склоняюсь к тому, что проблема на стороне MS SQL

Andreywys
освоился
освоился
Сообщения: 290
Зарегистрирован: 15 сен 2016, 18:47
Имя: Андрей
Страна: Россия
город/регион: Вологда
Благодарил (а): 19 раз
Поблагодарили: 76 раз

Сброс значений в SQL по времени

Сообщение Andreywys »

stesl писал(а): 16 июн 2019, 07:59 Ясно, ООП штучки :) Объекты, методы... Так комфортно было со своим Паскалем штанишки протирать...
Спасибо за, пусть и коротенькое, но объяснение чего то существенного.
https://www.youtube.com/watch?v=cdX8r3Z ... e=youtu.be
stesl писал(а): 16 июн 2019, 07:59 И это работает. А вот
Попробуйте вот так:

Код: Выделить всё

strSQL = "UPDATE Tab1 SET Dat =" & CStr(L_I_PRREAL.Read) & "WHERE Pos='L_I_SVR' "
Сименсовский vbs немного другой и то, что работает в обычном, не всегда работает в WinCC

Автор темы
stesl
эксперт
эксперт
Сообщения: 1008
Зарегистрирован: 31 мар 2018, 12:05
Имя: Вячеслав
Благодарил (а): 94 раза
Поблагодарили: 136 раз

Сброс значений в SQL по времени

Сообщение stesl »

Спасибо, я так пробовал, откликается - мол это ваще строковое значение и в эту ячейку SQL его никак...
Цитата не дословно. Но думаю не суть. Факт что не работает.

Отправлено спустя 5 минут 54 секунды:
Отдельное спасибо за ролик :crazy0to:
Только тут еще мухоморнее - папа может только Паскаль. С - ерэсь :) Не говоря уж о ++ и #
И не трудно вроде понять этот С. Синтаксис глаза режет. Пока десяток строк разберу - голова начинает болеть. Но как нибудь... С больной головой - прорвемся. VBS в свое время прочел книжонку, пару программ написал, и забыл вообще все что там было написано :ges_no:
Аватара пользователя

keysansa
эксперт
эксперт
Сообщения: 2330
Зарегистрирован: 20 дек 2018, 04:45
Имя: Сергей
Страна: РБ/РФ
город/регион: РФ Сергиев Посад
Благодарил (а): 1990 раз
Поблагодарили: 176 раз

Сброс значений в SQL по времени

Сообщение keysansa »

stesl писал(а): 18 июн 2019, 11:01 папа может только Паскаль
Представьте вызов

Код: Выделить всё

var = L_I_PRREAL.Read()

как

Код: Выделить всё

var = Read(record L_I_PRREAL)
Поможет )
В трансформаторной будке живет трансформаторная собака (с) Прозрачный гонщик.

Автор темы
stesl
эксперт
эксперт
Сообщения: 1008
Зарегистрирован: 31 мар 2018, 12:05
Имя: Вячеслав
Благодарил (а): 94 раза
Поблагодарили: 136 раз

Сброс значений в SQL по времени

Сообщение stesl »

Код: Выделить всё

var = Read(record L_I_PRREAL)
А чо работает? :crazy0to:
Я вообще то в душе никогда и не сомневался, что ноги у ООП выросли из типа Record Паскаля.
Ну а по теме - этот обмен с SQL нужен для обмена данными с другой прогой. На той стороне работает чел, который гораздо более шарит, настоящий прогер. Вот что он написал в почте:
Надо как-то посмотреть сфлрмированный запрос. Надо убедиться, что для разделения целой и дробной части в текстовом представлении вещественного чтсла используется точка. Это стандарт SQL для комманд, запятая имеет смысл разделителя в перечислениях, полей например. Возможно в vbs, например из-за русской локализации ОС, ставиться запятая. В качестве опыта можно попытаться записывать целые числа, если проблема с запятой, то все должно быть ок
В региональных настройках (а Виндэ конечно русская) сменил зпт на тчк и зашло на ура.
Надо бы теперь мне забирать с этой же базы рез-таты обработки (моих тэгов) его проги. Наверняка нюансы будут. Но вот про тчк - разобрались ;)

PS Ну а строка так и выглядит, как в самом начале изысканий

Код: Выделить всё

strSQL = "UPDATE Tab1 SET Dat =" & L_I_PRREAL.Read & "WHERE Pos='L_I_SVR' "
Отправлено спустя 17 минут 59 секунд:
Что то я расслабился. Есть же еще вопрос нерешенный.
Как пройтись по всем тэгам и сделать выборку имен только с ".AVERAGE". Т.e я понимаю как строку проверить на соответствие, но как указать проход по ВСЕМ тэгам. По их именам.

Можно вбить конечно все тэги нужные в какой то массив, как предлагает коллега выше, но
  • Количество таких тегов со временем точно изменится
  • Код с проходом будет выглядеть гораздо лаконичнее
  • Выполнятся он будет раз в сутки, так что особого влияния на общий ход работы не будет
Еще раз попробую сформулировать:
FROM начало таблицы имен TO конец этой таблицы DO вот тут я почти все понимаю что нужно написать
Как обозначить границы цикла?

Andreywys
освоился
освоился
Сообщения: 290
Зарегистрирован: 15 сен 2016, 18:47
Имя: Андрей
Страна: Россия
город/регион: Вологда
Благодарил (а): 19 раз
Поблагодарили: 76 раз

Сброс значений в SQL по времени

Сообщение Andreywys »

Вы же имена тегов в контроллере не меняете динамически? Изменили в контроллере - изменяйте в скрипте. Вы в таблице столбец тоже из скрипта добавлять будете? А потом frontend как узнает, что появилось новый столбец в таблице?
Зачем вы делаете update, а не insert? Для базы несколько миллионов значений - это ничего. А программеру сделать

Код: Выделить всё

SELECT TOP 1 * FROM Table ORDER BY ID DESC
не проблема. Зато у вас все значения сохранятся.

Автор темы
stesl
эксперт
эксперт
Сообщения: 1008
Зарегистрирован: 31 мар 2018, 12:05
Имя: Вячеслав
Благодарил (а): 94 раза
Поблагодарили: 136 раз

Сброс значений в SQL по времени

Сообщение stesl »

Зачем таблица в миллион значений?
На моменте добавления новых тегов - да, из скрипта, почему бы и нет. Немножко придется повозиться... хотя чего возиться - каждый раз очищаем таблицу под ноль и пишем новые значения. Тогда да, Update не нужен. А коллега просто забирает таблицу целиком. Как он там будет понимать, что кол-во тегов изменилось, и по каким надо считать - догадается.
Не знаю пока как это все выглядит с точки зрения SQL, но пока мне просто хотелось бы узнать - можно ли по тегам пройтись от начала до конца. А если нельзя - то может и тупо инсерт.

Отправлено спустя 6 минут 32 секунды:
Все это конечно не в духе БДзма, с его философией ключей и пр. Но по сути это просто буфер. По крайней мере я его так со своей колокольни вижу. Я вообще в блокнот предлагал. Но коллеге отчего то именно БД надо. Причем без всяких оговорок про ключи и оригинальность.

Автор темы
stesl
эксперт
эксперт
Сообщения: 1008
Зарегистрирован: 31 мар 2018, 12:05
Имя: Вячеслав
Благодарил (а): 94 раза
Поблагодарили: 136 раз

Сброс значений в SQL по времени

Сообщение stesl »

stesl писал(а): 19 июн 2019, 10:29 Как пройтись по всем тэгам и сделать выборку имен только с ".AVERAGE". Т.e я понимаю как строку проверить на соответствие, но как указать проход по ВСЕМ тэгам. По их именам.

Можно вбить конечно все тэги нужные в какой то массив, как предлагает коллега выше, но

Количество таких тегов со временем точно изменится

Код с проходом будет выглядеть гораздо лаконичнее

Выполнятся он будет раз в сутки, так что особого влияния на общий ход работы не будет

Еще раз попробую сформулировать:
FROM начало таблицы имен TO конец этой таблицы DO вот тут я почти все понимаю что нужно написать
Как обозначить границы цикла?
Коллеги, есть у кого то мысли?

Я вижу в разделе Standart Modules скрипт CheckVarStateQualityCode.bmo

Код: Выделить всё

Function CheckQualityCode_WinCC(CountVar, quality)

Dim BadOrUncertain, Limited, bInvalid, bFound
dim tmpQuali
Dim index, indexFound, indexPrio
Dim a

tmpQuali = Array(&Hff00, &Hff00, &Hff00, &H0040, &H0044, &H0048, &H004c, &H0078, &H0056, &H0055, &H0054, &H0060, &H0068, &Hff00, &H002b, &H0028, &H0000, &H0004, &H0008, &H000c, &H0014, &H0018, &H001c)

bFound = false
bInvalid = false

For a = 0 To CountVar-1
	BadOrUncertain = quality(a) And &H0080
	Limited = quality(a) AND &H0003
	
	if ((BadOrUncertain <> &H0080) OR ((Limited <> &H0000) AND (Limited <> &H0003))) then
		bInvalid = True
		Exit For
	End If
Next
........
На вход подается CountVar, а это, судя по предназначению скрипта - количество ВСЕХ переменных, и далее в цикле они обрабатываются. Естественно я не вижу вызова этого скрипта. Или не понимаю где его, вызов посмотреть. Но понимаю, что такая переменная - количество тегов есть, вроде...

Автор темы
stesl
эксперт
эксперт
Сообщения: 1008
Зарегистрирован: 31 мар 2018, 12:05
Имя: Вячеслав
Благодарил (а): 94 раза
Поблагодарили: 136 раз

Сброс значений в SQL по времени

Сообщение stesl »

Вот так в конце концов закрыл тему

Код: Выделить всё

'===== Данные для доступа к БД ==============
Dim TableName, Uname, DBPassword, DataBaseName, SQLServer
DataBaseName = "db"
Uname = "login"
DBPassword = "password"
SQLServer = "SRV"
TableName = "table"

'========= Инницируем соединение ===================
Dim SQLConnection, SQLConnectionString
SQLConnectionString = "Provider=SQLOLEDB.1;Persist Security Info=False;User ID=" & Uname _
 & ";Pwd=" & DBPassword & ";Initial Catalog=" & DataBaseName & ";Data Source=" & SQLServer & ""
Set SQLConnection = CreateObject("ADODB.Connection")
SQLConnection.ConnectionString = SQLConnectionString
SQLConnection.Open

'========== Создаем объект через который будем обращаться к БД ============
Dim SQLCommand
Set SQLCommand = CreateObject("ADODB.Command")
SQLCommand.ActiveConnection = SQLConnection

'========== Массив имен тегов для "сброса" в БД ============
Dim ArrayTags
ArrayTags = Array ("Q_I_1_1_5.SUMM", _
"Q_I_1_1_13.SUMM", _
"Q_I_1_2_3.SUMM", _
"Q_I_1_2_17.SUMM", _
"Q_I_1_3_5.SUMM", _
"Q_I_1_4_1.SUMM")

Dim SQLFields
SQLFields = " (channel, date1, value, status)"

'========== Оформляем данные для записи в цикле ================
Dim i, WinCCdata, Quality, WInCCtagName
For i = 0 To UBound(ArrayTags)
	WinCCtagName = ArrayTags(i)
	Set WinCCdata = HMIRuntime.Tags(WinCCtagName)
	WinCCdata.Read
	If (WinCCdata.QualityCode <> &H80) Or (WinCCdata.Value = 0) Then
		Quality = 0
	Else Quality = 1
	End If

'=========== Формируем строку SQL запроса ================
	Dim SQLQueryString, SQLValues
	SQLValues = " values ('" & WinCCtagName & "', CURRENT_TIMESTAMP, " & WinCCdata.Value & ", " & Quality & ")"
	SQLQueryString = "INSERT INTO " & TableName & SQLFields & SQLValues
	
'=========== Непосредственно запись ===================
	SQLCommand.CommandText = SQLQueryString
	SQLCommand.Execute

Next

'============= Разрываем созданные соединения ==============
Set SQLCommand = Nothing
SQLConnection.Close
Set SQLConnection = Nothing
Как видите, все теги имеют поле SUMM. А тегов не 5, как в примере, а 118 на данный момент ) И как было бы просто искать во всем поле тегов WinCC нужные. Но никто не знает как )

Ладно, теперь, по крайней мере можно просто добавлять имена тегов (любые) и кидать их в этот "файлообменник". Там уже сторонний разработчик их разгребает.
Ответить

Вернуться в «WinCC»